aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-10-28 01:11:27 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2021-10-28 01:11:27 +0000
commitfe6df087be3085e2a731c4ea7257ee95d98ed39e (patch)
tree6a4709841e622abaad951691e859a4ef59044903
parent550bcef47db9d580f4c075af0f431c5bf1aee448 (diff)
parent21d9798bf3aba5af94352a745f05065e691c88a7 (diff)
downloadopenssh-sdk-release.tar.gz
Merge "Snap for 7861008 from 439d58769bd64bbad36279188539209f2d4c2b07 to sdk-release" into sdk-releasesdk-release
-rw-r--r--.depend345
-rw-r--r--.github/ci-status.md4
-rwxr-xr-x.github/configs170
-rwxr-xr-x.github/configure.sh6
-rwxr-xr-x.github/run_test.sh34
-rwxr-xr-x.github/setup_ci.sh117
-rw-r--r--.github/workflows/c-cpp.yml81
-rw-r--r--.github/workflows/selfhosted.yml93
-rw-r--r--.github/workflows/upstream.yml43
-rw-r--r--.gitignore3
-rw-r--r--.skipped-commit-ids4
-rw-r--r--Android.bp9
-rw-r--r--INSTALL19
-rw-r--r--LICENCE62
-rw-r--r--METADATA4
-rw-r--r--Makefile.in119
-rw-r--r--PROTOCOL85
-rw-r--r--PROTOCOL.agent6
-rw-r--r--PROTOCOL.certkeys35
-rw-r--r--PROTOCOL.key9
-rw-r--r--PROTOCOL.sshsig3
-rw-r--r--PROTOCOL.u2f130
-rw-r--r--README2
-rw-r--r--README.md11
-rw-r--r--README.platform16
-rw-r--r--README.version4
-rw-r--r--addr.c423
-rw-r--r--addr.h60
-rw-r--r--addrmatch.c351
-rw-r--r--audit-bsm.c39
-rw-r--r--auth-krb5.c19
-rw-r--r--auth-options.c74
-rw-r--r--auth-options.h9
-rw-r--r--auth-pam.c18
-rw-r--r--auth-passwd.c6
-rw-r--r--auth-rhosts.c6
-rw-r--r--auth.c235
-rw-r--r--auth.h8
-rw-r--r--auth2-chall.c37
-rw-r--r--auth2-gss.c29
-rw-r--r--auth2-hostbased.c60
-rw-r--r--auth2-kbdint.c6
-rw-r--r--auth2-none.c4
-rw-r--r--auth2-passwd.c4
-rw-r--r--auth2-pubkey.c157
-rw-r--r--auth2.c88
-rw-r--r--authfd.c71
-rw-r--r--authfd.h6
-rw-r--r--authfile.c10
-rw-r--r--buildpkg.sh.in8
-rw-r--r--canohost.c8
-rw-r--r--chacha.h4
-rw-r--r--channels.c575
-rw-r--r--channels.h30
-rw-r--r--cipher.c10
-rw-r--r--clientloop.c634
-rw-r--r--compat.c93
-rw-r--r--compat.h20
-rw-r--r--configure.ac324
-rw-r--r--contrib/Makefile6
-rw-r--r--contrib/gnome-ssh-askpass1.c7
-rw-r--r--contrib/gnome-ssh-askpass2.c107
-rw-r--r--contrib/gnome-ssh-askpass3.c305
-rw-r--r--contrib/redhat/openssh.spec7
-rwxr-xr-xcontrib/redhat/sshd.init.old155
-rw-r--r--contrib/redhat/sshd.pam.old8
-rw-r--r--contrib/ssh-copy-id303
-rw-r--r--contrib/ssh-copy-id.19
-rw-r--r--contrib/suse/openssh.spec6
-rw-r--r--crypto_api.h18
-rw-r--r--defines.h17
-rw-r--r--dh.c29
-rw-r--r--dh.h3
-rw-r--r--digest-openssl.c10
-rw-r--r--dns.c71
-rw-r--r--dns.h3
-rw-r--r--entropy.c123
-rw-r--r--fatal.c7
-rw-r--r--gss-genr.c19
-rw-r--r--hash.c2
-rw-r--r--hostfile.c255
-rw-r--r--hostfile.h27
-rw-r--r--int32_minmax.inc0
-rw-r--r--kex.c139
-rw-r--r--kex.h18
-rw-r--r--kexdh.c6
-rw-r--r--kexgen.c26
-rw-r--r--kexgexc.c14
-rw-r--r--kexgexs.c7
-rw-r--r--kexsntrup761x25519.c (renamed from kexsntrup4591761x25519.c)84
-rw-r--r--krl.c111
-rw-r--r--log.c228
-rw-r--r--log.h91
-rw-r--r--loginrec.c3
-rw-r--r--loginrec.h2
-rw-r--r--logintest.c60
-rw-r--r--m4/openssh.m4 (renamed from aclocal.m4)32
-rw-r--r--match.c18
-rw-r--r--match.h6
-rw-r--r--misc.c732
-rw-r--r--misc.h53
-rw-r--r--moduli863
-rw-r--r--monitor.c411
-rw-r--r--monitor_fdpass.c24
-rw-r--r--monitor_wrap.c254
-rw-r--r--monitor_wrap.h7
-rw-r--r--msg.c18
-rw-r--r--mux.c607
-rw-r--r--myproposal.h18
-rw-r--r--nchan.c73
-rw-r--r--openbsd-compat/Makefile.in2
-rw-r--r--openbsd-compat/arc4random.c12
-rw-r--r--openbsd-compat/base64.c2
-rw-r--r--openbsd-compat/bcrypt_pbkdf.c4
-rw-r--r--openbsd-compat/bsd-misc.h6
-rw-r--r--openbsd-compat/bsd-poll.h2
-rw-r--r--openbsd-compat/bsd-pselect.c205
-rw-r--r--openbsd-compat/bsd-snprintf.c16
-rw-r--r--openbsd-compat/bsd-waitpid.h2
-rw-r--r--openbsd-compat/explicit_bzero.c10
-rw-r--r--openbsd-compat/getopt_long.c2
-rw-r--r--openbsd-compat/libressl-api-compat.c2
-rw-r--r--openbsd-compat/memmem.c221
-rw-r--r--openbsd-compat/mktemp.c4
-rw-r--r--openbsd-compat/openbsd-compat.h9
-rw-r--r--openbsd-compat/openssl-compat.h4
-rw-r--r--openbsd-compat/port-aix.c8
-rw-r--r--openbsd-compat/port-linux.c25
-rw-r--r--openbsd-compat/port-net.c10
-rw-r--r--openbsd-compat/port-prngd.c164
-rw-r--r--openbsd-compat/port-solaris.c8
-rw-r--r--openbsd-compat/port-uw.c2
-rw-r--r--openbsd-compat/regress/Makefile.in2
-rw-r--r--openbsd-compat/regress/closefromtest.c4
-rw-r--r--openbsd-compat/regress/opensslvertest.c2
-rw-r--r--openbsd-compat/regress/snprintftest.c2
-rw-r--r--openbsd-compat/regress/strduptest.c2
-rw-r--r--openbsd-compat/regress/strtonumtest.c2
-rw-r--r--openbsd-compat/regress/utimensattest.c2
-rw-r--r--openbsd-compat/setenv.c2
-rw-r--r--openbsd-compat/sha2.c4
-rw-r--r--openbsd-compat/strtonum.c6
-rw-r--r--openbsd-compat/sys-queue.h375
-rwxr-xr-xopensshd.init.in22
-rw-r--r--packet.c132
-rw-r--r--packet.h3
-rw-r--r--platform-tracing.c10
-rw-r--r--readconf.c1204
-rw-r--r--readconf.h29
-rw-r--r--readpass.c113
-rw-r--r--regress/Makefile27
-rw-r--r--regress/addrmatch.sh14
-rw-r--r--regress/agent-getpeereid.sh14
-rw-r--r--regress/agent-pkcs11.sh12
-rw-r--r--regress/agent-subprocess.sh22
-rw-r--r--regress/agent.sh77
-rw-r--r--regress/allow-deny-users.sh8
-rw-r--r--regress/banner.sh6
-rw-r--r--regress/cert-hostkey.sh16
-rw-r--r--regress/cert-userkey.sh22
-rw-r--r--regress/cfginclude.sh24
-rw-r--r--regress/cfgmatch.sh8
-rw-r--r--regress/connect-privsep.sh5
-rw-r--r--regress/dhgex.sh4
-rw-r--r--regress/ed25519_openssh.prv7
-rw-r--r--regress/ed25519_openssh.pub1
-rw-r--r--regress/exit-status-signal.sh24
-rw-r--r--regress/forward-control.sh6
-rw-r--r--regress/forwarding.sh8
-rw-r--r--regress/hostkey-rotate.sh26
-rw-r--r--regress/key-options.sh2
-rw-r--r--regress/keygen-convert.sh60
-rw-r--r--regress/keygen-sshfp.sh29
-rw-r--r--regress/keys-command.sh4
-rw-r--r--regress/keytype.sh6
-rw-r--r--regress/knownhosts-command.sh55
-rw-r--r--regress/limit-keytype.sh18
-rw-r--r--regress/misc/Makefile2
-rw-r--r--regress/misc/fuzz-harness/Makefile46
-rw-r--r--regress/misc/fuzz-harness/agent_fuzz.cc15
-rw-r--r--regress/misc/fuzz-harness/agent_fuzz_helper.c177
-rw-r--r--regress/misc/fuzz-harness/fixed-keys.h119
-rw-r--r--regress/misc/fuzz-harness/kex_fuzz.cc461
-rw-r--r--regress/misc/fuzz-harness/testdata/README4
-rwxr-xr-xregress/misc/fuzz-harness/testdata/create-agent-corpus.sh44
-rw-r--r--regress/misc/fuzz-harness/testdata/id_dsa21
-rw-r--r--regress/misc/fuzz-harness/testdata/id_dsa-cert.pub1
-rw-r--r--regress/misc/fuzz-harness/testdata/id_dsa.pub1
-rw-r--r--regress/misc/fuzz-harness/testdata/id_ecdsa8
-rw-r--r--regress/misc/fuzz-harness/testdata/id_ecdsa-cert.pub1
-rw-r--r--regress/misc/fuzz-harness/testdata/id_ecdsa.pub1
-rw-r--r--regress/misc/fuzz-harness/testdata/id_ecdsa_sk14
-rw-r--r--regress/misc/fuzz-harness/testdata/id_ecdsa_sk-cert.pub1
-rw-r--r--regress/misc/fuzz-harness/testdata/id_ecdsa_sk.pub1
-rw-r--r--regress/misc/fuzz-harness/testdata/id_ed255197
-rw-r--r--regress/misc/fuzz-harness/testdata/id_ed25519-cert.pub1
-rw-r--r--regress/misc/fuzz-harness/testdata/id_ed25519.pub2
-rw-r--r--regress/misc/fuzz-harness/testdata/id_ed25519_sk8
-rw-r--r--regress/misc/fuzz-harness/testdata/id_ed25519_sk-cert.pub1
-rw-r--r--regress/misc/fuzz-harness/testdata/id_ed25519_sk.pub1
-rw-r--r--regress/misc/fuzz-harness/testdata/id_rsa27
-rw-r--r--regress/misc/fuzz-harness/testdata/id_rsa-cert.pub1
-rw-r--r--regress/misc/fuzz-harness/testdata/id_rsa.pub1
-rw-r--r--regress/misc/kexfuzz/Makefile101
-rw-r--r--regress/misc/kexfuzz/README34
-rw-r--r--regress/misc/kexfuzz/kexfuzz.c453
-rw-r--r--regress/misc/sk-dummy/fatal.c11
-rw-r--r--regress/misc/sk-dummy/sk-dummy.c9
-rw-r--r--regress/multiplex.sh14
-rw-r--r--regress/multipubkey.sh19
-rw-r--r--regress/netcat.c41
-rw-r--r--regress/percent.sh53
-rw-r--r--regress/putty-ciphers.sh12
-rw-r--r--regress/putty-kex.sh12
-rw-r--r--regress/putty-transfer.sh12
-rw-r--r--regress/reconfigure.sh24
-rw-r--r--regress/rekey.sh8
-rw-r--r--regress/scp-uri.sh81
-rw-r--r--regress/scp.sh187
-rw-r--r--regress/scp3.sh60
-rw-r--r--regress/servcfginclude.sh44
-rw-r--r--regress/sftp-chroot.sh9
-rw-r--r--regress/sftp-perm.sh18
-rwxr-xr-xregress/ssh2putty.sh8
-rw-r--r--regress/sshcfgparse.sh39
-rw-r--r--regress/sshfp-connect.sh66
-rw-r--r--regress/sshsig.sh52
-rw-r--r--regress/test-exec.sh161
-rw-r--r--regress/unittests/Makefile4
-rw-r--r--regress/unittests/authopt/Makefile4
-rw-r--r--regress/unittests/authopt/tests.c10
-rw-r--r--regress/unittests/conversion/Makefile3
-rw-r--r--regress/unittests/conversion/tests.c34
-rw-r--r--regress/unittests/hostkeys/Makefile4
-rw-r--r--regress/unittests/hostkeys/test_iterate.c91
-rw-r--r--regress/unittests/kex/Makefile8
-rw-r--r--regress/unittests/kex/test_kex.c6
-rw-r--r--regress/unittests/match/Makefile4
-rw-r--r--regress/unittests/match/tests.c4
-rw-r--r--regress/unittests/misc/Makefile23
-rw-r--r--regress/unittests/misc/test_argv.c187
-rw-r--r--regress/unittests/misc/test_convtime.c59
-rw-r--r--regress/unittests/misc/test_expand.c90
-rw-r--r--regress/unittests/misc/test_parse.c86
-rw-r--r--regress/unittests/misc/test_strdelim.c202
-rw-r--r--regress/unittests/misc/tests.c77
-rw-r--r--regress/unittests/sshbuf/Makefile3
-rw-r--r--regress/unittests/sshkey/Makefile4
-rwxr-xr-xregress/unittests/sshkey/mktestdata.sh53
-rw-r--r--regress/unittests/sshkey/test_file.c133
-rw-r--r--regress/unittests/sshkey/test_fuzz.c4
-rw-r--r--regress/unittests/sshkey/test_sshkey.c9
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_sk113
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_sk1-cert.fp1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_sk1-cert.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_sk1.fp1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_sk1.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_sk1.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_sk1_pw14
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_sk213
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_sk2.fp1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_sk2.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_sk2.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_sk18
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_sk1-cert.fp1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_sk1-cert.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_sk1.fp1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_sk1.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_sk1.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_sk1_pw9
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_sk28
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_sk2.fp1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_sk2.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_sk2.pub1
-rw-r--r--regress/unittests/sshsig/Makefile25
-rwxr-xr-xregress/unittests/sshsig/mktestdata.sh42
-rw-r--r--regress/unittests/sshsig/testdata/dsa12
-rw-r--r--regress/unittests/sshsig/testdata/dsa.pub1
-rw-r--r--regress/unittests/sshsig/testdata/dsa.sig13
-rw-r--r--regress/unittests/sshsig/testdata/ecdsa5
-rw-r--r--regress/unittests/sshsig/testdata/ecdsa.pub1
-rw-r--r--regress/unittests/sshsig/testdata/ecdsa.sig7
-rw-r--r--regress/unittests/sshsig/testdata/ecdsa_sk13
-rw-r--r--regress/unittests/sshsig/testdata/ecdsa_sk.pub1
-rw-r--r--regress/unittests/sshsig/testdata/ecdsa_sk.sig8
-rw-r--r--regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.pub1
-rw-r--r--regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.sig13
-rw-r--r--regress/unittests/sshsig/testdata/ed255197
-rw-r--r--regress/unittests/sshsig/testdata/ed25519.pub1
-rw-r--r--regress/unittests/sshsig/testdata/ed25519.sig6
-rw-r--r--regress/unittests/sshsig/testdata/ed25519_sk8
-rw-r--r--regress/unittests/sshsig/testdata/ed25519_sk.pub1
-rw-r--r--regress/unittests/sshsig/testdata/ed25519_sk.sig7
-rw-r--r--regress/unittests/sshsig/testdata/namespace1
-rw-r--r--regress/unittests/sshsig/testdata/rsa39
-rw-r--r--regress/unittests/sshsig/testdata/rsa.pub1
-rw-r--r--regress/unittests/sshsig/testdata/rsa.sig19
-rw-r--r--regress/unittests/sshsig/testdata/signed-data1
-rw-r--r--regress/unittests/sshsig/tests.c139
-rw-r--r--regress/unittests/sshsig/webauthn.html766
-rwxr-xr-xregress/valgrind-unit.sh2
-rw-r--r--sandbox-pledge.c8
-rw-r--r--sandbox-rlimit.c18
-rw-r--r--sandbox-seccomp-filter.c18
-rw-r--r--scp.172
-rw-r--r--scp.c539
-rw-r--r--servconf.c884
-rw-r--r--servconf.h36
-rw-r--r--serverloop.c201
-rw-r--r--session.c204
-rw-r--r--sftp-client.c1101
-rw-r--r--sftp-client.h61
-rw-r--r--sftp-common.c4
-rw-r--r--sftp-realpath.c3
-rw-r--r--sftp-server.830
-rw-r--r--sftp-server.c399
-rw-r--r--sftp.144
-rw-r--r--sftp.c126
-rw-r--r--sk-api.h9
-rw-r--r--sk-usbhid.c642
-rw-r--r--sntrup4591761.c1083
-rw-r--r--sntrup4591761.sh57
-rw-r--r--sntrup761.c1273
-rw-r--r--sntrup761.sh85
-rw-r--r--srclimit.c140
-rw-r--r--srclimit.h18
-rw-r--r--ssh-add.135
-rw-r--r--ssh-add.c130
-rw-r--r--ssh-agent.126
-rw-r--r--ssh-agent.c653
-rw-r--r--ssh-ecdsa-sk.c169
-rw-r--r--ssh-ed25519-sk.c5
-rw-r--r--ssh-ed25519.c5
-rw-r--r--ssh-gss.h4
-rw-r--r--ssh-keygen.186
-rw-r--r--ssh-keygen.c721
-rw-r--r--ssh-keyscan.c42
-rw-r--r--ssh-keysign.c57
-rw-r--r--ssh-pkcs11-client.c53
-rw-r--r--ssh-pkcs11-helper.c76
-rw-r--r--ssh-pkcs11.c117
-rw-r--r--ssh-sk-client.c83
-rw-r--r--ssh-sk-helper.c58
-rw-r--r--ssh-sk.c141
-rw-r--r--ssh-xmss.c9
-rw-r--r--ssh.185
-rw-r--r--ssh.c574
-rw-r--r--ssh.h7
-rw-r--r--ssh2.h4
-rw-r--r--ssh_api.c49
-rw-r--r--ssh_config3
-rw-r--r--ssh_config.5445
-rw-r--r--sshbuf-getput-basic.c4
-rw-r--r--sshbuf-misc.c49
-rw-r--r--sshbuf.h6
-rw-r--r--sshconnect.c571
-rw-r--r--sshconnect.h47
-rw-r--r--sshconnect2.c492
-rw-r--r--sshd.869
-rw-r--r--sshd.c405
-rw-r--r--sshd_config10
-rw-r--r--sshd_config.5188
-rw-r--r--sshkey-xmss.c55
-rw-r--r--sshkey-xmss.h16
-rw-r--r--sshkey.c162
-rw-r--r--sshkey.h30
-rw-r--r--sshlogin.c4
-rw-r--r--sshpty.c1
-rw-r--r--sshsig.c243
-rw-r--r--sshsig.h13
-rw-r--r--ttymodes.c44
-rw-r--r--uidswap.c2
-rw-r--r--umac.c4
-rw-r--r--utf8.h10
-rw-r--r--version.h4
-rw-r--r--xmalloc.h7
376 files changed, 20478 insertions, 10850 deletions
diff --git a/.depend b/.depend
index 1ccc1dcc7..a94a82d0e 100644
--- a/.depend
+++ b/.depend
@@ -2,179 +2,182 @@
# Run "make depend" to rebuild.
# DO NOT DELETE
-addrmatch.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h match.h log.h
-atomicio.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h atomicio.h
-audit-bsm.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-audit-linux.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-audit.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-auth-bsdauth.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-auth-krb5.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h sshbuf.h sshkey.h misc.h servconf.h uidswap.h hostfile.h auth.h auth-pam.h audit.h loginrec.h
-auth-options.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssherr.h log.h sshbuf.h misc.h sshkey.h match.h ssh2.h auth-options.h
-auth-pam.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-auth-passwd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h packet.h openbsd-compat/sys-queue.h dispatch.h sshbuf.h ssherr.h log.h misc.h servconf.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h
-auth-rhosts.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h packet.h openbsd-compat/sys-queue.h dispatch.h uidswap.h pathnames.h log.h misc.h sshbuf.h sshkey.h servconf.h canohost.h hostfile.h auth.h auth-pam.h audit.h loginrec.h
-auth-shadow.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-auth-sia.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-auth.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h match.h groupaccess.h log.h sshbuf.h misc.h servconf.h openbsd-compat/sys-queue.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h canohost.h uidswap.h packet.h dispatch.h authfile.h
-auth.o: monitor_wrap.h ssherr.h compat.h channels.h
-auth2-chall.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh2.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h sshbuf.h packet.h openbsd-compat/sys-queue.h dispatch.h ssherr.h log.h misc.h servconf.h
-auth2-gss.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-auth2-hostbased.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h sshbuf.h log.h misc.h servconf.h compat.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h canohost.h monitor_wrap.h pathnames.h
-auth2-hostbased.o: ssherr.h match.h
-auth2-kbdint.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h packet.h openbsd-compat/sys-queue.h dispatch.h hostfile.h auth.h auth-pam.h audit.h loginrec.h log.h misc.h servconf.h ssherr.h
-auth2-none.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h atomicio.h xmalloc.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h misc.h servconf.h compat.h ssh2.h ssherr.h monitor_wrap.h
-auth2-passwd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h packet.h openbsd-compat/sys-queue.h dispatch.h ssherr.h log.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h monitor_wrap.h misc.h servconf.h
-auth2-pubkey.o: canohost.h monitor_wrap.h authfile.h match.h ssherr.h channels.h session.h sk-api.h
-auth2-pubkey.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h sshbuf.h log.h misc.h servconf.h compat.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h pathnames.h uidswap.h auth-options.h
+addr.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h addr.h
+addrmatch.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h addr.h match.h log.h ssherr.h
+atomicio.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h atomicio.h
+audit-bsm.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+audit-linux.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+audit.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+auth-bsdauth.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+auth-krb5.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h ssherr.h sshbuf.h sshkey.h misc.h servconf.h uidswap.h hostfile.h auth.h auth-pam.h audit.h loginrec.h
+auth-options.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssherr.h log.h sshbuf.h misc.h sshkey.h match.h ssh2.h auth-options.h
+auth-pam.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+auth-passwd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h packet.h openbsd-compat/sys-queue.h dispatch.h sshbuf.h ssherr.h log.h misc.h servconf.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h
+auth-rhosts.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h packet.h openbsd-compat/sys-queue.h dispatch.h uidswap.h pathnames.h log.h ssherr.h misc.h sshbuf.h sshkey.h servconf.h canohost.h hostfile.h auth.h auth-pam.h audit.h loginrec.h
+auth-shadow.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+auth-sia.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+auth.o: authfile.h monitor_wrap.h compat.h channels.h
+auth.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h match.h groupaccess.h log.h ssherr.h sshbuf.h misc.h servconf.h openbsd-compat/sys-queue.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h canohost.h uidswap.h packet.h dispatch.h
+auth2-chall.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh2.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h sshbuf.h packet.h openbsd-compat/sys-queue.h dispatch.h ssherr.h log.h misc.h servconf.h
+auth2-gss.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+auth2-hostbased.o: canohost.h monitor_wrap.h pathnames.h match.h
+auth2-hostbased.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h kex.h mac.h crypto_api.h sshbuf.h log.h ssherr.h misc.h servconf.h compat.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h
+auth2-kbdint.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h packet.h openbsd-compat/sys-queue.h dispatch.h hostfile.h auth.h auth-pam.h audit.h loginrec.h log.h ssherr.h misc.h servconf.h
+auth2-none.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h atomicio.h xmalloc.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h ssherr.h misc.h servconf.h compat.h ssh2.h monitor_wrap.h
+auth2-passwd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h packet.h openbsd-compat/sys-queue.h dispatch.h ssherr.h log.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h monitor_wrap.h misc.h servconf.h
+auth2-pubkey.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h kex.h mac.h crypto_api.h sshbuf.h log.h ssherr.h misc.h servconf.h compat.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h
+auth2-pubkey.o: pathnames.h uidswap.h auth-options.h canohost.h monitor_wrap.h authfile.h match.h channels.h session.h sk-api.h
auth2.o: digest.h
-auth2.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h atomicio.h xmalloc.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h sshbuf.h misc.h servconf.h compat.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h pathnames.h ssherr.h monitor_wrap.h
-authfd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh.h sshbuf.h sshkey.h authfd.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h compat.h log.h atomicio.h misc.h ssherr.h
-authfile.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h ssh.h log.h authfile.h misc.h atomicio.h sshkey.h sshbuf.h ssherr.h krl.h
-bitmap.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h bitmap.h
-canohost.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h canohost.h misc.h
-chacha.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h chacha.h
-channels.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h ssherr.h sshbuf.h packet.h dispatch.h log.h misc.h channels.h compat.h canohost.h sshkey.h authfd.h pathnames.h match.h
-cipher-aes.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/openssl-compat.h
-cipher-aesctr.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h cipher-aesctr.h rijndael.h
-cipher-chachapoly-libcrypto.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-cipher-chachapoly.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h sshbuf.h ssherr.h cipher-chachapoly.h chacha.h poly1305.h
-cipher-ctr.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-cipher.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h misc.h sshbuf.h ssherr.h digest.h openbsd-compat/openssl-compat.h
-cleanup.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h
-clientloop.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h packet.h dispatch.h sshbuf.h compat.h channels.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h
-clientloop.o: myproposal.h log.h misc.h readconf.h clientloop.h sshconnect.h authfd.h atomicio.h sshpty.h match.h msg.h ssherr.h hostfile.h
-compat.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h packet.h openbsd-compat/sys-queue.h dispatch.h compat.h log.h match.h kex.h mac.h crypto_api.h
-dh.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-digest-libc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h digest.h
-digest-openssl.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-dispatch.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh2.h log.h dispatch.h packet.h openbsd-compat/sys-queue.h compat.h ssherr.h
-dns.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h sshkey.h ssherr.h dns.h log.h digest.h
-ed25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h ge25519.h fe25519.h sc25519.h
-entropy.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-fatal.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h
-fe25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h fe25519.h crypto_api.h
-ge25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h fe25519.h crypto_api.h sc25519.h ge25519.h ge25519_base.data
-groupaccess.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h groupaccess.h match.h log.h
-gss-genr.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-gss-serv-krb5.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-gss-serv.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-hash.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h
-hmac.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshbuf.h digest.h hmac.h
-hostfile.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h match.h sshkey.h hostfile.h log.h misc.h ssherr.h digest.h hmac.h
-kex.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh.h ssh2.h atomicio.h version.h packet.h openbsd-compat/sys-queue.h dispatch.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h log.h match.h
-kex.o: misc.h monitor.h ssherr.h sshbuf.h digest.h
-kexc25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshkey.h kex.h mac.h crypto_api.h sshbuf.h digest.h ssherr.h ssh2.h
-kexdh.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-kexecdh.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h
-kexgen.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshkey.h kex.h mac.h crypto_api.h log.h packet.h openbsd-compat/sys-queue.h dispatch.h ssh2.h sshbuf.h digest.h ssherr.h
-kexgex.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-kexgexc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-kexgexs.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-kexsntrup4591761x25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshkey.h kex.h mac.h crypto_api.h sshbuf.h digest.h ssherr.h
-krl.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h sshbuf.h ssherr.h sshkey.h authfile.h misc.h log.h digest.h bitmap.h utf8.h krl.h
-log.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h
-loginrec.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h sshkey.h hostfile.h ssh.h loginrec.h log.h atomicio.h packet.h openbsd-compat/sys-queue.h dispatch.h canohost.h auth.h auth-pam.h audit.h sshbuf.h ssherr.h
-logintest.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h loginrec.h
-mac.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h digest.h hmac.h umac.h mac.h misc.h ssherr.h sshbuf.h openbsd-compat/openssl-compat.h
-match.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h match.h misc.h
-md5crypt.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-misc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h misc.h log.h ssh.h sshbuf.h ssherr.h
-moduli.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-monitor.o: chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h dh.h packet.h dispatch.h auth-options.h sshpty.h channels.h session.h sshlogin.h canohost.h log.h misc.h servconf.h monitor.h monitor_wrap.h monitor_fdpass.h compat.h ssh2.h authfd.h match.h ssherr.h sk-api.h
-monitor.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h openbsd-compat/openssl-compat.h atomicio.h xmalloc.h ssh.h sshkey.h sshbuf.h hostfile.h auth.h auth-pam.h audit.h loginrec.h cipher.h cipher-chachapoly.h
-monitor_fdpass.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h monitor_fdpass.h
-monitor_wrap.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h sshbuf.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h hostfile.h auth.h auth-pam.h audit.h
-monitor_wrap.o: loginrec.h auth-options.h packet.h dispatch.h log.h monitor.h monitor_wrap.h atomicio.h monitor_fdpass.h misc.h channels.h session.h servconf.h ssherr.h
-msg.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshbuf.h ssherr.h log.h atomicio.h msg.h misc.h
-mux.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h log.h ssh.h ssh2.h pathnames.h misc.h match.h sshbuf.h channels.h msg.h packet.h dispatch.h monitor_fdpass.h sshpty.h sshkey.h readconf.h clientloop.h ssherr.h
-nchan.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h ssh2.h sshbuf.h ssherr.h packet.h dispatch.h channels.h compat.h log.h
-packet.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h compat.h ssh2.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h digest.h log.h canohost.h misc.h channels.h ssh.h
-packet.o: packet.h dispatch.h ssherr.h sshbuf.h
-platform-misc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-platform-pledge.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-platform-tracing.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h
-platform.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h misc.h servconf.h openbsd-compat/sys-queue.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h
-poly1305.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h poly1305.h
-progressmeter.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h progressmeter.h atomicio.h misc.h utf8.h
-readconf.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/glob.h xmalloc.h ssh.h ssherr.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h pathnames.h log.h sshkey.h misc.h readconf.h match.h kex.h mac.h crypto_api.h
+auth2.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h atomicio.h xmalloc.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h ssherr.h sshbuf.h misc.h servconf.h compat.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h pathnames.h monitor_wrap.h
+authfd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh.h sshbuf.h sshkey.h authfd.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h compat.h log.h ssherr.h atomicio.h misc.h
+authfile.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h ssh.h log.h ssherr.h authfile.h misc.h atomicio.h sshkey.h sshbuf.h krl.h
+bitmap.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h bitmap.h
+canohost.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h ssherr.h canohost.h misc.h
+chacha.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h chacha.h
+channels.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h ssherr.h sshbuf.h packet.h dispatch.h log.h misc.h channels.h compat.h canohost.h sshkey.h authfd.h pathnames.h match.h
+cipher-aes.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/openssl-compat.h
+cipher-aesctr.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h cipher-aesctr.h rijndael.h
+cipher-chachapoly-libcrypto.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+cipher-chachapoly.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h sshbuf.h cipher-chachapoly.h chacha.h poly1305.h
+cipher-ctr.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+cipher.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h misc.h sshbuf.h ssherr.h digest.h openbsd-compat/openssl-compat.h
+cleanup.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h
+clientloop.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h packet.h dispatch.h sshbuf.h compat.h channels.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h
+clientloop.o: myproposal.h log.h ssherr.h misc.h readconf.h clientloop.h sshconnect.h authfd.h atomicio.h sshpty.h match.h msg.h hostfile.h
+compat.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h packet.h openbsd-compat/sys-queue.h dispatch.h compat.h log.h ssherr.h match.h kex.h mac.h crypto_api.h
+dh.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+digest-libc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h digest.h
+digest-openssl.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+dispatch.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh2.h log.h ssherr.h dispatch.h packet.h openbsd-compat/sys-queue.h compat.h
+dns.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h sshkey.h ssherr.h dns.h log.h digest.h
+ed25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h ge25519.h fe25519.h sc25519.h
+entropy.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+fatal.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h
+fe25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-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 fe25519.h crypto_api.h
+ge25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-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 fe25519.h crypto_api.h sc25519.h ge25519.h ge25519_base.data
+groupaccess.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h groupaccess.h match.h log.h ssherr.h
+gss-genr.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+gss-serv-krb5.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+gss-serv.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+hash.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h
+hmac.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshbuf.h digest.h hmac.h
+hostfile.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h match.h sshkey.h hostfile.h log.h ssherr.h misc.h pathnames.h digest.h hmac.h sshbuf.h
+kex.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh.h ssh2.h atomicio.h version.h packet.h openbsd-compat/sys-queue.h dispatch.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h log.h ssherr.h
+kex.o: match.h misc.h monitor.h sshbuf.h digest.h
+kexc25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshkey.h kex.h mac.h crypto_api.h sshbuf.h digest.h ssherr.h ssh2.h
+kexdh.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+kexecdh.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h
+kexgen.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshkey.h kex.h mac.h crypto_api.h log.h ssherr.h packet.h openbsd-compat/sys-queue.h dispatch.h ssh2.h sshbuf.h digest.h
+kexgex.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+kexgexc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+kexgexs.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+kexsntrup761x25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h
+krl.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h sshbuf.h ssherr.h sshkey.h authfile.h misc.h log.h digest.h bitmap.h utf8.h krl.h
+log.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h match.h
+loginrec.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h sshkey.h hostfile.h ssh.h loginrec.h log.h ssherr.h atomicio.h packet.h openbsd-compat/sys-queue.h dispatch.h canohost.h auth.h auth-pam.h audit.h sshbuf.h
+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
+md5crypt.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-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
+misc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h misc.h log.h ssherr.h ssh.h sshbuf.h
+moduli.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+monitor.o: chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h dh.h packet.h dispatch.h auth-options.h sshpty.h channels.h session.h sshlogin.h canohost.h log.h ssherr.h misc.h servconf.h monitor.h monitor_wrap.h monitor_fdpass.h compat.h ssh2.h authfd.h match.h sk-api.h
+monitor.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h openbsd-compat/openssl-compat.h atomicio.h xmalloc.h ssh.h sshkey.h sshbuf.h hostfile.h auth.h auth-pam.h audit.h loginrec.h cipher.h cipher-chachapoly.h
+monitor_fdpass.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h monitor_fdpass.h
+monitor_wrap.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h sshbuf.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h hostfile.h auth.h auth-pam.h audit.h
+monitor_wrap.o: loginrec.h auth-options.h packet.h dispatch.h log.h ssherr.h monitor.h monitor_wrap.h atomicio.h monitor_fdpass.h misc.h channels.h session.h servconf.h
+msg.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshbuf.h ssherr.h log.h atomicio.h msg.h misc.h
+mux.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h log.h ssherr.h ssh.h ssh2.h pathnames.h misc.h match.h sshbuf.h channels.h msg.h packet.h dispatch.h monitor_fdpass.h sshpty.h sshkey.h readconf.h clientloop.h
+nchan.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h ssh2.h sshbuf.h ssherr.h packet.h dispatch.h channels.h compat.h log.h
+packet.o: channels.h ssh.h packet.h dispatch.h sshbuf.h
+packet.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h compat.h ssh2.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h digest.h log.h ssherr.h canohost.h misc.h
+platform-misc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+platform-pledge.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+platform-tracing.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h
+platform.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h misc.h servconf.h openbsd-compat/sys-queue.h sshkey.h hostfile.h auth.h auth-pam.h audit.h loginrec.h
+poly1305.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h poly1305.h
+progressmeter.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h progressmeter.h atomicio.h misc.h utf8.h
+readconf.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/glob.h xmalloc.h ssh.h ssherr.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h pathnames.h log.h sshkey.h misc.h readconf.h match.h kex.h mac.h crypto_api.h
readconf.o: uidswap.h myproposal.h digest.h
-readpass.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h misc.h pathnames.h log.h ssh.h uidswap.h
-rijndael.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h rijndael.h
-sandbox-capsicum.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-sandbox-darwin.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-sandbox-null.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-sandbox-pledge.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-sandbox-rlimit.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-sandbox-seccomp-filter.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-sandbox-solaris.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-sandbox-systrace.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-sc25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sc25519.h crypto_api.h
-scp.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh.h atomicio.h pathnames.h log.h misc.h progressmeter.h utf8.h
-servconf.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/glob.h openbsd-compat/sys-queue.h xmalloc.h ssh.h log.h sshbuf.h misc.h servconf.h compat.h pathnames.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h
-servconf.o: mac.h crypto_api.h match.h channels.h groupaccess.h canohost.h packet.h dispatch.h ssherr.h hostfile.h auth.h auth-pam.h audit.h loginrec.h myproposal.h digest.h
-serverloop.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h packet.h dispatch.h sshbuf.h log.h misc.h servconf.h canohost.h sshpty.h channels.h compat.h ssh2.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h
-serverloop.o: rijndael.h kex.h mac.h crypto_api.h hostfile.h auth.h auth-pam.h audit.h loginrec.h session.h auth-options.h serverloop.h ssherr.h
-session.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshpty.h packet.h dispatch.h sshbuf.h ssherr.h match.h uidswap.h compat.h channels.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h
+readpass.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h misc.h pathnames.h log.h ssherr.h ssh.h uidswap.h
+rijndael.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h rijndael.h
+sandbox-capsicum.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+sandbox-darwin.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+sandbox-null.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+sandbox-pledge.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+sandbox-rlimit.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+sandbox-seccomp-filter.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+sandbox-solaris.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+sandbox-systrace.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+sc25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-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 sc25519.h crypto_api.h
+scp.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/glob.h xmalloc.h ssh.h atomicio.h pathnames.h log.h ssherr.h misc.h progressmeter.h utf8.h sftp-common.h sftp-client.h
+servconf.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/glob.h openbsd-compat/sys-queue.h xmalloc.h ssh.h log.h ssherr.h sshbuf.h misc.h servconf.h compat.h pathnames.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h
+servconf.o: kex.h mac.h crypto_api.h match.h channels.h groupaccess.h canohost.h packet.h dispatch.h hostfile.h auth.h auth-pam.h audit.h loginrec.h myproposal.h digest.h
+serverloop.o: cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h hostfile.h auth.h auth-pam.h audit.h loginrec.h session.h auth-options.h serverloop.h
+serverloop.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-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 compat.h ssh2.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h
+session.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-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 compat.h channels.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h
session.o: rijndael.h hostfile.h auth.h auth-pam.h audit.h loginrec.h auth-options.h authfd.h pathnames.h log.h misc.h servconf.h sshlogin.h serverloop.h canohost.h session.h kex.h mac.h crypto_api.h monitor_wrap.h sftp.h atomicio.h
-sftp-client.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssherr.h sshbuf.h log.h atomicio.h progressmeter.h misc.h utf8.h sftp.h sftp-common.h sftp-client.h openbsd-compat/glob.h
-sftp-common.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssherr.h sshbuf.h log.h misc.h sftp.h sftp-common.h
-sftp-glob.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h sftp.h sftp-common.h sftp-client.h openbsd-compat/glob.h
-sftp-realpath.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-sftp-server-main.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h sftp.h misc.h xmalloc.h
-sftp-server.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h sshbuf.h ssherr.h log.h misc.h match.h uidswap.h sftp.h sftp-common.h
-sftp.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h log.h pathnames.h misc.h utf8.h sftp.h ssherr.h sshbuf.h sftp-common.h sftp-client.h openbsd-compat/glob.h
-sk-usbhid.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-sntrup4591761.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h
-ssh-add.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh.h log.h sshkey.h sshbuf.h authfd.h authfile.h pathnames.h misc.h ssherr.h digest.h ssh-sk.h
-ssh-agent.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h sshbuf.h sshkey.h authfd.h compat.h log.h misc.h digest.h ssherr.h match.h msg.h pathnames.h ssh-pkcs11.h sk-api.h
-ssh-dss.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-ssh-ecdsa-sk.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/openssl-compat.h sshbuf.h ssherr.h digest.h sshkey.h
-ssh-ecdsa.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-ssh-ed25519-sk.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h log.h sshbuf.h sshkey.h ssherr.h ssh.h digest.h
-ssh-ed25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h log.h sshbuf.h sshkey.h ssherr.h ssh.h
-ssh-keygen.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h sshkey.h authfile.h sshbuf.h pathnames.h log.h misc.h match.h hostfile.h dns.h ssh.h ssh2.h ssherr.h ssh-pkcs11.h atomicio.h krl.h digest.h utf8.h authfd.h sshsig.h ssh-sk.h sk-api.h
-ssh-keyscan.o: atomicio.h misc.h hostfile.h ssherr.h ssh_api.h ssh2.h dns.h
-ssh-keyscan.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h sshbuf.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h compat.h myproposal.h packet.h dispatch.h log.h
-ssh-keysign.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h log.h sshkey.h ssh.h ssh2.h misc.h sshbuf.h authfile.h msg.h canohost.h pathnames.h readconf.h uidswap.h ssherr.h
-ssh-pkcs11-client.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-ssh-pkcs11-helper.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h sshbuf.h log.h misc.h sshkey.h authfd.h ssh-pkcs11.h ssherr.h
-ssh-pkcs11.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h sshkey.h
-ssh-rsa.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-ssh-sk-client.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h sshbuf.h sshkey.h msg.h digest.h pathnames.h ssh-sk.h misc.h
-ssh-sk-helper.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h log.h sshkey.h authfd.h misc.h sshbuf.h msg.h uidswap.h ssherr.h ssh-sk.h
-ssh-sk.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-ssh-xmss.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-ssh.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/openssl-compat.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h canohost.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h packet.h dispatch.h sshbuf.h channels.h
-ssh.o: sshkey.h authfd.h authfile.h pathnames.h clientloop.h log.h misc.h readconf.h sshconnect.h kex.h mac.h crypto_api.h sshpty.h match.h msg.h version.h ssherr.h myproposal.h utf8.h
-ssh_api.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh_api.h openbsd-compat/sys-queue.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h ssh.h ssh2.h packet.h dispatch.h compat.h log.h authfile.h misc.h
-ssh_api.o: version.h myproposal.h ssherr.h sshbuf.h openbsd-compat/openssl-compat.h
-sshbuf-getput-basic.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h
-sshbuf-getput-crypto.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-sshbuf-io.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h atomicio.h
-sshbuf-misc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h
-sshbuf.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h misc.h
+sftp-client.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssherr.h sshbuf.h log.h atomicio.h progressmeter.h misc.h utf8.h sftp.h sftp-common.h sftp-client.h openbsd-compat/glob.h
+sftp-common.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssherr.h sshbuf.h log.h misc.h sftp.h sftp-common.h
+sftp-glob.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h sftp.h sftp-common.h sftp-client.h openbsd-compat/glob.h
+sftp-realpath.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+sftp-server-main.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h sftp.h misc.h xmalloc.h
+sftp-server.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h sshbuf.h ssherr.h log.h misc.h match.h uidswap.h sftp.h sftp-common.h
+sftp.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h log.h ssherr.h pathnames.h misc.h utf8.h sftp.h sshbuf.h sftp-common.h sftp-client.h openbsd-compat/glob.h
+sk-usbhid.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+sntrup761.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+srclimit.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h addr.h canohost.h log.h ssherr.h misc.h srclimit.h xmalloc.h
+ssh-add.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h ssh.h log.h ssherr.h sshkey.h sshbuf.h authfd.h authfile.h pathnames.h misc.h digest.h ssh-sk.h sk-api.h
+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 compat.h log.h ssherr.h misc.h digest.h match.h msg.h pathnames.h ssh-pkcs11.h sk-api.h
+ssh-dss.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+ssh-ecdsa-sk.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/openssl-compat.h sshbuf.h ssherr.h digest.h sshkey.h
+ssh-ecdsa.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+ssh-ed25519-sk.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h log.h ssherr.h sshbuf.h sshkey.h ssh.h digest.h
+ssh-ed25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h log.h ssherr.h sshbuf.h sshkey.h ssh.h
+ssh-keygen.o: cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h
+ssh-keygen.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h sshkey.h authfile.h sshbuf.h pathnames.h log.h ssherr.h misc.h match.h hostfile.h dns.h ssh.h ssh2.h ssh-pkcs11.h atomicio.h krl.h digest.h utf8.h authfd.h sshsig.h ssh-sk.h sk-api.h cipher.h
+ssh-keyscan.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h sshbuf.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h crypto_api.h compat.h myproposal.h packet.h dispatch.h log.h
+ssh-keyscan.o: ssherr.h atomicio.h misc.h hostfile.h ssh_api.h ssh2.h dns.h
+ssh-keysign.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h log.h ssherr.h sshkey.h ssh.h ssh2.h misc.h sshbuf.h authfile.h msg.h canohost.h pathnames.h readconf.h uidswap.h
+ssh-pkcs11-client.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+ssh-pkcs11-helper.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h sshbuf.h log.h ssherr.h misc.h sshkey.h authfd.h ssh-pkcs11.h
+ssh-pkcs11.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h sshkey.h
+ssh-rsa.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+ssh-sk-client.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h sshbuf.h sshkey.h msg.h digest.h pathnames.h ssh-sk.h misc.h
+ssh-sk-helper.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h log.h ssherr.h sshkey.h authfd.h misc.h sshbuf.h msg.h uidswap.h ssh-sk.h
+ssh-sk.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+ssh-xmss.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+ssh.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/openssl-compat.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h canohost.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h packet.h dispatch.h sshbuf.h channels.h
+ssh.o: sshkey.h authfd.h authfile.h pathnames.h clientloop.h log.h ssherr.h misc.h readconf.h sshconnect.h kex.h mac.h crypto_api.h sshpty.h match.h msg.h version.h myproposal.h utf8.h
+ssh_api.o: authfile.h misc.h version.h myproposal.h sshbuf.h openbsd-compat/openssl-compat.h
+ssh_api.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh_api.h openbsd-compat/sys-queue.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h ssh.h ssh2.h packet.h dispatch.h compat.h log.h ssherr.h
+sshbuf-getput-basic.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h
+sshbuf-getput-crypto.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+sshbuf-io.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h atomicio.h
+sshbuf-misc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h
+sshbuf.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h misc.h
sshconnect.o: authfd.h kex.h mac.h crypto_api.h
-sshconnect.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h hostfile.h ssh.h sshbuf.h packet.h openbsd-compat/sys-queue.h dispatch.h compat.h sshkey.h sshconnect.h log.h misc.h readconf.h atomicio.h dns.h monitor_fdpass.h ssh2.h version.h authfile.h ssherr.h
-sshconnect2.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshbuf.h packet.h dispatch.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h
-sshconnect2.o: myproposal.h sshconnect.h authfile.h dh.h authfd.h log.h misc.h readconf.h match.h canohost.h msg.h pathnames.h uidswap.h hostfile.h ssherr.h utf8.h ssh-sk.h sk-api.h
-sshd.o: cipher-aesctr.h rijndael.h digest.h sshkey.h kex.h mac.h crypto_api.h myproposal.h authfile.h pathnames.h atomicio.h canohost.h hostfile.h auth.h auth-pam.h audit.h loginrec.h authfd.h msg.h channels.h session.h monitor.h monitor_wrap.h ssh-sandbox.h auth-options.h version.h ssherr.h sk-api.h
-sshd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshpty.h packet.h dispatch.h log.h sshbuf.h misc.h match.h servconf.h uidswap.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h
+sshconnect.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h hostfile.h ssh.h sshbuf.h packet.h openbsd-compat/sys-queue.h dispatch.h compat.h sshkey.h sshconnect.h log.h ssherr.h misc.h readconf.h atomicio.h dns.h monitor_fdpass.h ssh2.h version.h authfile.h
+sshconnect2.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshbuf.h packet.h dispatch.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h crypto_api.h
+sshconnect2.o: myproposal.h sshconnect.h authfile.h dh.h authfd.h log.h ssherr.h misc.h readconf.h match.h canohost.h msg.h pathnames.h uidswap.h hostfile.h utf8.h ssh-sk.h sk-api.h
+sshd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshpty.h packet.h dispatch.h log.h ssherr.h sshbuf.h misc.h match.h servconf.h uidswap.h compat.h cipher.h cipher-chachapoly.h chacha.h
+sshd.o: poly1305.h cipher-aesctr.h rijndael.h digest.h sshkey.h kex.h mac.h crypto_api.h myproposal.h authfile.h pathnames.h atomicio.h canohost.h hostfile.h auth.h auth-pam.h audit.h loginrec.h authfd.h msg.h channels.h session.h monitor.h monitor_wrap.h ssh-sandbox.h auth-options.h version.h sk-api.h srclimit.h dh.h
ssherr.o: ssherr.h
-sshkey-xmss.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-sshkey.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h ssh2.h ssherr.h misc.h sshbuf.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h sshkey.h match.h ssh-sk.h openbsd-compat/openssl-compat.h
-sshlogin.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshlogin.h ssherr.h loginrec.h log.h sshbuf.h misc.h servconf.h openbsd-compat/sys-queue.h
-sshpty.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshpty.h log.h misc.h
-sshsig.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h authfd.h authfile.h log.h misc.h sshbuf.h sshsig.h ssherr.h sshkey.h match.h digest.h
-sshtty.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshpty.h
-ttymodes.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h compat.h sshbuf.h ssherr.h ttymodes.h
-uidswap.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h uidswap.h xmalloc.h
-umac.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h umac.h misc.h rijndael.h
-umac128.o: umac.c includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h umac.h misc.h rijndael.h
-utf8.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h utf8.h
-verify.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h
-xmalloc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h log.h
-xmss_commons.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-xmss_fast.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-xmss_hash.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-xmss_hash_address.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
-xmss_wots.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+sshkey-xmss.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h
+sshkey.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h crypto_api.h ssh2.h ssherr.h misc.h sshbuf.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h sshkey.h match.h ssh-sk.h openbsd-compat/openssl-compat.h
+sshlogin.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshlogin.h ssherr.h loginrec.h log.h sshbuf.h misc.h servconf.h openbsd-compat/sys-queue.h
+sshpty.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshpty.h log.h ssherr.h misc.h
+sshsig.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h authfd.h authfile.h log.h ssherr.h misc.h sshbuf.h sshsig.h sshkey.h match.h digest.h
+sshtty.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshpty.h
+ttymodes.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h packet.h openbsd-compat/sys-queue.h dispatch.h log.h ssherr.h compat.h sshbuf.h ttymodes.h
+uidswap.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h log.h ssherr.h uidswap.h xmalloc.h
+umac.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h umac.h misc.h rijndael.h
+umac128.o: umac.c includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h umac.h misc.h rijndael.h
+utf8.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h utf8.h
+verify.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/fnmatch.h openbsd-compat/getopt.h openbsd-compat/bsd-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
+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/ci-status.md b/.github/ci-status.md
new file mode 100644
index 000000000..0ad8bf5aa
--- /dev/null
+++ b/.github/ci-status.md
@@ -0,0 +1,4 @@
+[![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)
+[![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)
+[![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)
+[![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)
diff --git a/.github/configs b/.github/configs
new file mode 100755
index 000000000..12578c067
--- /dev/null
+++ b/.github/configs
@@ -0,0 +1,170 @@
+#!/bin/sh
+#
+# usage: configs vmname test_config (or '' for default)
+#
+# Sets the following variables:
+# CONFIGFLAGS options to ./configure
+# SSHD_CONFOPTS sshd_config options
+# TEST_TARGET make target used when testing. defaults to "tests".
+# LTESTS
+
+config=$1
+
+TEST_TARGET="tests"
+LTESTS=""
+SKIP_LTESTS=""
+SUDO=sudo # run with sudo by default
+TEST_SSH_UNSAFE_PERMISSIONS=1
+
+CONFIGFLAGS=""
+LIBCRYPTOFLAGS=""
+
+case "$config" in
+ default|sol64)
+ ;;
+ c89)
+ CC="gcc"
+ CFLAGS="-Wall -std=c89 -pedantic -Werror=vla"
+ CONFIGFLAGS="--without-openssl --without-zlib"
+ TEST_TARGET=t-exec
+ ;;
+ kitchensink)
+ CONFIGFLAGS="--with-kerberos5 --with-libedit --with-pam"
+ CONFIGFLAGS="${CONFIGFLAGS} --with-security-key-builtin --with-selinux"
+ CONFIGFLAGS="${CONFIGFLAGS} --with-cflags=-DSK_DEBUG"
+ ;;
+ hardenedmalloc)
+ CONFIGFLAGS="--with-ldflags=-lhardened_malloc"
+ ;;
+ kerberos5)
+ CONFIGFLAGS="--with-kerberos5"
+ ;;
+ libedit)
+ CONFIGFLAGS="--with-libedit"
+ ;;
+ pam-krb5)
+ CONFIGFLAGS="--with-pam --with-kerberos5"
+ SSHD_CONFOPTS="UsePam yes"
+ ;;
+ *pam)
+ CONFIGFLAGS="--with-pam"
+ SSHD_CONFOPTS="UsePam yes"
+ ;;
+ libressl-*)
+ LIBCRYPTOFLAGS="--with-ssl-dir=/opt/libressl --with-rpath=-Wl,-rpath,"
+ ;;
+ openssl-*)
+ LIBCRYPTOFLAGS="--with-ssl-dir=/opt/openssl --with-rpath=-Wl,-rpath,"
+ ;;
+ selinux)
+ CONFIGFLAGS="--with-selinux"
+ ;;
+ sk)
+ CONFIGFLAGS="--with-security-key-builtin"
+ ;;
+ without-openssl)
+ LIBCRYPTOFLAGS="--without-openssl"
+ TEST_TARGET=t-exec
+ ;;
+ valgrind-[1-4]|valgrind-unit)
+ # rlimit sandbox and FORTIFY_SOURCE confuse Valgrind.
+ CONFIGFLAGS="--without-sandbox --without-hardening"
+ CONFIGFLAGS="$CONFIGFLAGS --with-cppflags=-D_FORTIFY_SOURCE=0"
+ TEST_TARGET="t-exec USE_VALGRIND=1"
+ TEST_SSH_ELAPSED_TIMES=1
+ export TEST_SSH_ELAPSED_TIMES
+ # Valgrind slows things down enough that the agent timeout test
+ # won't reliably pass, and the unit tests run longer than allowed
+ # by github so split into three separate tests.
+ tests2="rekey integrity"
+ tests3="krl forward-control sshsig"
+ tests4="cert-userkey cert-hostkey kextype sftp-perm keygen-comment"
+ case "$config" in
+ valgrind-1)
+ # All tests except agent-timeout (which is flaky under valgrind)
+ #) and slow ones that run separately to increase parallelism.
+ SKIP_LTESTS="agent-timeout ${tests2} ${tests3} ${tests4}"
+ ;;
+ valgrind-2)
+ LTESTS="${tests2}"
+ ;;
+ valgrind-3)
+ LTESTS="${tests3}"
+ ;;
+ valgrind-4)
+ LTESTS="${tests4}"
+ ;;
+ valgrind-unit)
+ TEST_TARGET="unit USE_VALGRIND=1"
+ ;;
+ esac
+ ;;
+ *)
+ echo "Unknown configuration $config"
+ exit 1
+ ;;
+esac
+
+# The Solaris 64bit targets are special since they need a non-flag arg.
+case "$config" in
+ sol64*)
+ CONFIGFLAGS="x86_64 --with-cflags=-m64 --with-ldflags=-m64 ${CONFIGFLAGS}"
+ LIBCRYPTOFLAGS="--with-ssl-dir=/usr/local/ssl64"
+ ;;
+esac
+
+case "${TARGET_HOST}" in
+ dfly58*|dfly60*)
+ # scp 3-way connection hangs on these so skip until sorted.
+ SKIP_LTESTS=scp3
+ ;;
+ hurd)
+ SKIP_LTESTS="forwarding multiplex proxy-connect hostkey-agent agent-ptrace"
+ ;;
+ minix3)
+ CC="clang"
+ LIBCRYPTOFLAGS="--without-openssl"
+ # Minix does not have a loopback interface so we have to skip any
+ # test that relies on it.
+ TEST_TARGET=t-exec
+ SKIP_LTESTS="addrmatch cfgparse key-options reexec agent connect"
+ SKIP_LTESTS="$SKIP_LTESTS keyscan rekey allow-deny-users connect-uri"
+ SKIP_LTESTS="$SKIP_LTESTS knownhosts-command sftp-uri brokenkeys"
+ SKIP_LTESTS="$SKIP_LTESTS exit-status login-timeout stderr-data"
+ SKIP_LTESTS="$SKIP_LTESTS cfgmatch forward-control multiplex transfer"
+ SKIP_LTESTS="$SKIP_LTESTS cfgmatchlisten forwarding reconfigure"
+ SUDO=""
+ ;;
+ nbsd4)
+ # System compiler will ICE on some files with fstack-protector
+ CONFIGFLAGS="${CONFIGFLAGS} --without-hardening"
+ ;;
+ sol10|sol11)
+ # sol10 VM is 32bit and the unit tests are slow.
+ # sol11 has 4 test configs so skip unit tests to speed up.
+ TEST_TARGET="tests SKIP_UNIT=1"
+ ;;
+ win10)
+ # No sudo on Windows.
+ SUDO=""
+ ;;
+esac
+
+# If we have a local openssl/libressl, use that.
+if [ -z "${LIBCRYPTOFLAGS}" ]; then
+ # last-match
+ for i in /usr/local /usr/local/ssl /usr/local/opt/openssl; do
+ if [ -x ${i}/bin/openssl ]; then
+ LIBCRYPTOFLAGS="--with-ssl-dir=${i}"
+ fi
+ done
+fi
+
+CONFIGFLAGS="${CONFIGFLAGS} ${LIBCRYPTOFLAGS}"
+
+if [ -x "$(which plink 2>/dev/null)" ]; then
+ REGRESS_INTEROP_PUTTY=yes
+ export REGRESS_INTEROP_PUTTY
+fi
+
+export CC CFLAGS LTESTS SUDO TEST_TARGET TEST_SSH_UNSAFE_PERMISSIONS
diff --git a/.github/configure.sh b/.github/configure.sh
new file mode 100755
index 000000000..e098730f0
--- /dev/null
+++ b/.github/configure.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+. .github/configs $1
+
+set -x
+./configure ${CONFIGFLAGS}
diff --git a/.github/run_test.sh b/.github/run_test.sh
new file mode 100755
index 000000000..adf2568ad
--- /dev/null
+++ b/.github/run_test.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+. .github/configs $1
+
+[ -z "${SUDO}" ] || ${SUDO} mkdir -p /var/empty
+
+set -ex
+
+output_failed_logs() {
+ for i in regress/failed*; do
+ if [ -f "$i" ]; then
+ echo -------------------------------------------------------------------------
+ echo LOGFILE $i
+ cat $i
+ echo -------------------------------------------------------------------------
+ fi
+ done
+}
+trap output_failed_logs 0
+
+if [ -z "${LTESTS}" ]; then
+ make ${TEST_TARGET} SKIP_LTESTS="${SKIP_LTESTS}"
+else
+ make ${TEST_TARGET} SKIP_LTESTS="${SKIP_LTESTS}" LTESTS="${LTESTS}"
+fi
+
+if [ ! -z "${SSHD_CONFOPTS}" ]; then
+ echo "rerunning t-exec with TEST_SSH_SSHD_CONFOPTS='${SSHD_CONFOPTS}'"
+ if [ -z "${LTESTS}" ]; then
+ make t-exec SKIP_LTESTS="${SKIP_LTESTS}" TEST_SSH_SSHD_CONFOPTS="${SSHD_CONFOPTS}"
+ else
+ make t-exec SKIP_LTESTS="${SKIP_LTESTS}" LTESTS="${LTESTS}" TEST_SSH_SSHD_CONFOPTS="${SSHD_CONFOPTS}"
+ fi
+fi
diff --git a/.github/setup_ci.sh b/.github/setup_ci.sh
new file mode 100755
index 000000000..107c049c4
--- /dev/null
+++ b/.github/setup_ci.sh
@@ -0,0 +1,117 @@
+#!/bin/sh
+
+case $(./config.guess) in
+*-darwin*)
+ brew install automake
+ exit 0
+ ;;
+esac
+
+TARGETS=$@
+
+PACKAGES=""
+INSTALL_FIDO_PPA="no"
+export DEBIAN_FRONTEND=noninteractive
+
+#echo "Setting up for '$TARGETS'"
+
+set -ex
+
+lsb_release -a
+
+if [ "${TARGETS}" = "kitchensink" ]; then
+ TARGETS="kerberos5 libedit pam sk selinux"
+fi
+
+for TARGET in $TARGETS; do
+ case $TARGET in
+ default|without-openssl|without-zlib|c89)
+ # nothing to do
+ ;;
+ kerberos5)
+ PACKAGES="$PACKAGES heimdal-dev"
+ #PACKAGES="$PACKAGES libkrb5-dev"
+ ;;
+ libedit)
+ PACKAGES="$PACKAGES libedit-dev"
+ ;;
+ *pam)
+ PACKAGES="$PACKAGES libpam0g-dev"
+ ;;
+ sk)
+ INSTALL_FIDO_PPA="yes"
+ PACKAGES="$PACKAGES libfido2-dev libu2f-host-dev libcbor-dev"
+ ;;
+ selinux)
+ PACKAGES="$PACKAGES libselinux1-dev selinux-policy-dev"
+ ;;
+ hardenedmalloc)
+ INSTALL_HARDENED_MALLOC=yes
+ ;;
+ openssl-noec)
+ INSTALL_OPENSSL=OpenSSL_1_1_1k
+ SSLCONFOPTS="no-ec"
+ ;;
+ openssl-*)
+ INSTALL_OPENSSL=$(echo ${TARGET} | cut -f2 -d-)
+ case ${INSTALL_OPENSSL} in
+ 1.1.1_stable) INSTALL_OPENSSL="OpenSSL_1_1_1-stable" ;;
+ 1.*) INSTALL_OPENSSL="OpenSSL_$(echo ${INSTALL_OPENSSL} | tr . _)" ;;
+ 3.*) INSTALL_OPENSSL="openssl-${INSTALL_OPENSSL}" ;;
+ esac
+ PACKAGES="${PACKAGES} putty-tools"
+ ;;
+ libressl-*)
+ INSTALL_LIBRESSL=$(echo ${TARGET} | cut -f2 -d-)
+ case ${INSTALL_LIBRESSL} in
+ master) ;;
+ *) INSTALL_LIBRESSL="v$(echo ${TARGET} | cut -f2 -d-)" ;;
+ esac
+ PACKAGES="${PACKAGES} putty-tools"
+ ;;
+ valgrind*)
+ PACKAGES="$PACKAGES valgrind"
+ ;;
+ *) echo "Invalid option '${TARGET}'"
+ exit 1
+ ;;
+ esac
+done
+
+if [ "yes" = "$INSTALL_FIDO_PPA" ]; then
+ sudo apt update -qq
+ sudo apt install -qy software-properties-common
+ sudo apt-add-repository -y ppa:yubico/stable
+fi
+
+if [ "x" != "x$PACKAGES" ]; then
+ sudo apt update -qq
+ sudo apt install -qy $PACKAGES
+fi
+
+if [ "${INSTALL_HARDENED_MALLOC}" = "yes" ]; then
+ (cd ${HOME} &&
+ git clone https://github.com/GrapheneOS/hardened_malloc.git &&
+ cd ${HOME}/hardened_malloc &&
+ make -j2 && sudo cp libhardened_malloc.so /usr/lib/)
+fi
+
+if [ ! -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)
+fi
+
+if [ ! -z "${INSTALL_LIBRESSL}" ]; then
+ (mkdir -p ${HOME}/libressl && cd ${HOME}/libressl &&
+ git clone https://github.com/libressl-portable/portable.git &&
+ cd ${HOME}/libressl/portable &&
+ git checkout ${INSTALL_LIBRESSL} &&
+ sh update.sh && sh autogen.sh &&
+ ./configure --prefix=/opt/libressl &&
+ make -j2 && sudo make install)
+fi
diff --git a/.github/workflows/c-cpp.yml b/.github/workflows/c-cpp.yml
new file mode 100644
index 000000000..152ddaa4f
--- /dev/null
+++ b/.github/workflows/c-cpp.yml
@@ -0,0 +1,81 @@
+name: C/C++ CI
+
+on:
+ push:
+ branches: [ master, ci ]
+ pull_request:
+ branches: [ master ]
+
+jobs:
+ ci:
+ if: github.repository != 'openssh/openssh-portable-selfhosted'
+ strategy:
+ fail-fast: false
+ matrix:
+ # First we test all OSes in the default configuration.
+ os: [ubuntu-20.04, ubuntu-18.04, macos-10.15, macos-11.0]
+ configs: [default]
+ # Then we include any extra configs we want to test for specific VMs.
+ # Valgrind slows things down quite a bit, so start them first.
+ include:
+ - { os: ubuntu-20.04, configs: valgrind-1 }
+ - { os: ubuntu-20.04, configs: valgrind-2 }
+ - { os: ubuntu-20.04, configs: valgrind-3 }
+ - { os: ubuntu-20.04, configs: valgrind-4 }
+ - { os: ubuntu-20.04, configs: valgrind-unit }
+ - { os: ubuntu-20.04, configs: c89 }
+ - { os: ubuntu-20.04, configs: pam }
+ - { os: ubuntu-20.04, configs: kitchensink }
+ - { os: ubuntu-20.04, configs: hardenedmalloc }
+ - { os: ubuntu-latest, configs: libressl-master }
+ - { os: ubuntu-latest, configs: libressl-2.2.9 }
+ - { os: ubuntu-latest, configs: libressl-2.8.3 }
+ - { os: ubuntu-latest, configs: libressl-3.0.2 }
+ - { os: ubuntu-latest, configs: libressl-3.2.6 }
+ - { os: ubuntu-latest, configs: libressl-3.3.4 }
+ - { os: ubuntu-latest, configs: libressl-3.4.0 }
+ - { os: ubuntu-latest, configs: openssl-master }
+ - { os: ubuntu-latest, configs: openssl-noec }
+ - { os: ubuntu-latest, configs: openssl-1.0.1 }
+ - { os: ubuntu-latest, configs: openssl-1.0.1u }
+ - { os: ubuntu-latest, configs: openssl-1.0.2u }
+ - { os: ubuntu-latest, configs: openssl-1.1.0h }
+ - { os: ubuntu-latest, configs: openssl-1.1.1 }
+ - { os: ubuntu-latest, configs: openssl-1.1.1k }
+ - { os: ubuntu-latest, configs: openssl-3.0.0 }
+ - { os: ubuntu-latest, configs: openssl-1.1.1_stable } # stable branch
+ - { os: ubuntu-latest, configs: openssl-3.0 } # stable branch
+ - { os: ubuntu-18.04, configs: pam }
+ - { os: ubuntu-18.04, configs: kerberos5 }
+ - { os: ubuntu-18.04, configs: libedit }
+ - { os: ubuntu-18.04, configs: sk }
+ - { os: ubuntu-18.04, configs: selinux }
+ - { os: ubuntu-18.04, configs: kitchensink }
+ - { os: ubuntu-18.04, configs: without-openssl }
+ - { os: macos-10.15, configs: pam }
+ - { os: macos-11.0, configs: pam }
+ runs-on: ${{ matrix.os }}
+ steps:
+ - uses: actions/checkout@v2
+ - name: setup CI system
+ run: ./.github/setup_ci.sh ${{ matrix.configs }}
+ - name: autoreconf
+ run: autoreconf
+ - name: configure
+ run: ./.github/configure.sh ${{ matrix.configs }}
+ - name: make
+ run: make -j2
+ - name: make tests
+ run: ./.github/run_test.sh ${{ matrix.configs }}
+ env:
+ TEST_SSH_UNSAFE_PERMISSIONS: 1
+ - name: save logs
+ if: failure()
+ uses: actions/upload-artifact@v2
+ with:
+ name: ${{ matrix.os }}-${{ matrix.configs }}-logs
+ path: |
+ config.h
+ config.log
+ regress/*.log
+ regress/valgrind-out/
diff --git a/.github/workflows/selfhosted.yml b/.github/workflows/selfhosted.yml
new file mode 100644
index 000000000..df6eca714
--- /dev/null
+++ b/.github/workflows/selfhosted.yml
@@ -0,0 +1,93 @@
+name: C/C++ CI self-hosted
+
+on:
+ push:
+ branches: [ master, ci ]
+
+jobs:
+ selfhosted:
+ if: github.repository == 'openssh/openssh-portable-selfhosted'
+ runs-on: ${{ matrix.os }}
+ env:
+ TARGET_HOST: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ # We use a matrix in two parts: firstly all of the VMs are tested with the
+ # default config. "os" corresponds to a label associated with the worker.
+ matrix:
+ os:
+ - ARM64
+ - bbone
+ - dfly30
+ - dfly48
+ - dfly58
+ - dfly60
+ - fbsd6
+ - fbsd10
+ - fbsd12
+ - fbsd13
+ - hurd
+ - minix3
+ # - nbsd2
+ - nbsd3
+ - nbsd4
+ - nbsd8
+ - nbsd9
+ - obsd51
+ - obsd67
+ - obsd68
+ - obsd69
+ - obsdsnap
+ - openindiana
+ # - rocky84
+ - sol10
+ - sol11
+ - win10
+ configs:
+ - default
+ # Then we include any extra configs we want to test for specific VMs.
+ include:
+ - { os: ARM64, configs: pam }
+ - { os: dfly30, configs: without-openssl}
+ - { os: dfly48, configs: pam }
+ - { os: dfly58, configs: pam }
+ - { os: dfly60, configs: pam }
+ - { os: fbsd6, configs: pam }
+ - { os: fbsd10, configs: pam }
+ - { os: fbsd12, configs: pam }
+ - { os: fbsd13, configs: pam }
+ - { os: nbsd8, configs: pam }
+ - { os: nbsd9, configs: pam }
+ - { os: openindiana, configs: pam }
+ # - { os: rocky84, configs: pam }
+ - { os: sol10, configs: pam }
+ - { os: sol11, configs: pam-krb5 }
+ - { os: sol11, configs: sol64 }
+ # - { os: sol11, configs: sol64-pam }
+ steps:
+ - uses: actions/checkout@v2
+ - name: autoreconf
+ run: autoreconf
+ - name: shutdown VM if running
+ run: vmshutdown
+ - name: startup VM
+ run: vmstartup
+ - name: configure
+ run: vmrun ./.github/configure.sh ${{ matrix.configs }}
+ - name: make
+ run: vmrun make
+ - name: make tests
+ run: vmrun ./.github/run_test.sh ${{ matrix.configs }}
+ - name: save logs
+ if: failure()
+ uses: actions/upload-artifact@v2
+ with:
+ name: ${{ matrix.os }}-${{ matrix.configs }}-logs
+ path: |
+ config.h
+ config.log
+ regress/*.log
+ regress/valgrind-out/
+ - name: shutdown VM
+ if: always()
+ run: vmshutdown
diff --git a/.github/workflows/upstream.yml b/.github/workflows/upstream.yml
new file mode 100644
index 000000000..f0493c12d
--- /dev/null
+++ b/.github/workflows/upstream.yml
@@ -0,0 +1,43 @@
+name: Upstream self-hosted
+
+on:
+ push:
+ branches: [ master, ci ]
+
+jobs:
+ selfhosted:
+ if: github.repository == 'openssh/openssh-portable-selfhosted'
+ runs-on: ${{ matrix.os }}
+ env:
+ TARGET_HOST: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ obsdsnap, obsdsnap-i386, obsd69, obsd68 ]
+ configs: [ default, without-openssl ]
+ steps:
+ - uses: actions/checkout@v2
+ - name: shutdown VM if running
+ run: vmshutdown
+ - name: startup VM
+ run: vmstartup
+ - name: update source
+ run: vmrun "cd /usr/src && cvs up -dPA usr.bin/ssh regress/usr.bin/ssh"
+ - name: make clean
+ run: vmrun "cd /usr/src/usr.bin/ssh && make obj && make clean"
+ - name: make
+ run: vmrun "cd /usr/src/usr.bin/ssh && if test '${{ matrix.configs }}' = 'without-openssl'; then make OPENSSL=no; else make; fi"
+ - name: make install
+ run: vmrun "cd /usr/src/usr.bin/ssh && sudo make install"
+ - name: make tests
+ run: vmrun "cd /usr/src/regress/usr.bin/ssh && make obj && make clean && if test '${{ matrix.configs }}' = 'without-openssl'; then make SUDO=sudo OPENSSL=no; else make SUDO=sudo; fi"
+ - name: save logs
+ if: failure()
+ uses: actions/upload-artifact@v2
+ with:
+ name: ${{ matrix.os }}-${{ matrix.configs }}-logs
+ path: |
+ /usr/obj/regress/usr.bin/ssh/*.log
+ - name: shutdown VM
+ if: always()
+ run: vmshutdown
diff --git a/.gitignore b/.gitignore
index 34a95721d..5e4ae5a60 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,9 +2,11 @@ Makefile
buildpkg.sh
config.h
config.h.in
+config.h.in~
config.log
config.status
configure
+aclocal.m4
openbsd-compat/Makefile
openbsd-compat/regress/Makefile
openssh.xml
@@ -30,4 +32,5 @@ ssh-pkcs11-helper
ssh-sk-helper
sshd
!regress/misc/fuzz-harness/Makefile
+!regress/unittests/sshsig/Makefile
tags
diff --git a/.skipped-commit-ids b/.skipped-commit-ids
index 611d1093d..1de781722 100644
--- a/.skipped-commit-ids
+++ b/.skipped-commit-ids
@@ -19,6 +19,10 @@ d9b910e412d139141b072a905e66714870c38ac0 Makefile.inc
7b7b619c1452a459310b0cf4391c5757c6bdbc0f moduli update
5010ff08f7ad92082e87dde098b20f5c24921a8f moduli regen script update
3bcae7a754db3fc5ad3cab63dd46774edb35b8ae moduli regen script update
+52ff0e3205036147b2499889353ac082e505ea54 moduli update
+07b5031e9f49f2b69ac5e85b8da4fc9e393992a0 Makefile.inc
+cc12a9029833d222043aecd252d654965c351a69 moduli-gen Makefile
+7ac6c252d2a5be8fbad4c66d9d35db507c9dac5b moduli update
Old upstream tree:
diff --git a/Android.bp b/Android.bp
index f48e34019..6b016bfc8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -74,6 +74,7 @@ cc_library {
defaults: ["ssh_defaults"],
cflags: ["-DENABLE_SK"],
srcs: [
+ "addr.c",
"addrmatch.c",
"atomicio.c",
"authfd.c",
@@ -109,7 +110,7 @@ cc_library {
"kexgen.c",
"kexgex.c",
"kexgexc.c",
- "kexsntrup4591761x25519.c",
+ "kexsntrup761x25519.c",
"krl.c",
"log.c",
"mac.c",
@@ -158,8 +159,8 @@ cc_library {
"readpass.c",
"rijndael.c",
"sc25519.c",
- "sntrup4591761.c",
"smult_curve25519_ref.c",
+ "sntrup761.c",
"ssh-dss.c",
"ssh-ecdsa.c",
"ssh-ecdsa-sk.c",
@@ -217,6 +218,9 @@ cc_binary {
defaults: ["ssh_defaults"],
srcs: [
"scp.c",
+ "sftp-client.c",
+ "sftp-common.c",
+ "sftp-glob.c",
"progressmeter.c",
],
shared_libs: ["libssh"],
@@ -264,6 +268,7 @@ cc_binary {
"sftp-common.c",
"sftp-realpath.c",
"sftp-server.c",
+ "srclimit.c",
"sshd.c",
"sshlogin.c",
"sshpty.c",
diff --git a/INSTALL b/INSTALL
index 443ff9f3f..dddd912c5 100644
--- a/INSTALL
+++ b/INSTALL
@@ -97,11 +97,12 @@ http://nlnetlabs.nl/projects/ldns/
Autoconf:
If you modify configure.ac or configure doesn't exist (eg if you checked
-the code out of git yourself) then you will need autoconf-2.69 to rebuild
-the automatically generated files by running "autoreconf". Earlier
-versions may also work but this is not guaranteed.
+the code out of git yourself) then you will need autoconf-2.69 and
+automake-1.16.1 to rebuild the automatically generated files by running
+"autoreconf". Earlier versions may also work but this is not guaranteed.
http://www.gnu.org/software/autoconf/
+http://www.gnu.org/software/automake/
Basic Security Module (BSM):
@@ -120,7 +121,8 @@ the dependency (.depend) file using "make depend", which requires the
libfido2:
libfido2 allows the use of hardware security keys over USB. libfido2
-in turn depends on libcbor.
+in turn depends on libcbor. libfido2 >= 1.5.0 is strongly recommended.
+Limited functionality is possible with earlier libfido2 versions.
https://github.com/Yubico/libfido2
https://github.com/pjk/libcbor
@@ -221,6 +223,11 @@ libraries are installed.
--with-ssl-engine enables Libre/OpenSSL's (hardware) ENGINE support
+--without-openssl builds without using OpenSSL. Only a subset of ciphers
+and algorithms are supported in this configuration.
+
+--without-zlib builds without zlib. This disables the Compression option.
+
--with-4in6 Check for IPv4 in IPv6 mapped addresses and convert them to
real (AF_INET) IPv4 addresses. Works around some quirks on Linux.
@@ -254,8 +261,8 @@ Replacing /etc/ssh with the correct path to the configuration directory.
(${prefix}/etc or whatever you specified with --sysconfdir during
configuration).
-If you have configured OpenSSH with EGD support, ensure that EGD is
-running and has collected some Entropy.
+If you have configured OpenSSH with EGD/prngd support, ensure that EGD or
+prngd is running and has collected some entropy first.
For more information on configuration, please refer to the manual pages
for sshd, ssh and ssh-agent.
diff --git a/LICENCE b/LICENCE
index a2278a05d..5999c5e9d 100644
--- a/LICENCE
+++ b/LICENCE
@@ -314,6 +314,68 @@ OpenSSH contains no GPL code.
* authorization. *
****************************************************************************/
+ The Blowfish cipher implementation is licensed by Niels Provis under
+ a 4-clause BSD license:
+
+ * Blowfish - a fast block cipher designed by Bruce Schneier
+ *
+ * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Niels Provos.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Some replacement code is licensed by the NetBSD foundation under a
+ 2-clause BSD license:
+
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Todd Vierling.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
------
$OpenBSD: LICENCE,v 1.20 2017/04/30 23:26:16 djm Exp $
diff --git a/METADATA b/METADATA
index eef037a7d..aeee37fdb 100644
--- a/METADATA
+++ b/METADATA
@@ -11,7 +11,7 @@ third_party {
type: GIT
value: "https://github.com/openssh/openssh-portable"
}
- version: "8.3p1"
- last_upgrade_date { year: 2020 month: 8 day: 20 }
+ version: "8.8p1"
+ last_upgrade_date { year: 2021 month: 10 day: 21 }
license_type: NOTICE
}
diff --git a/Makefile.in b/Makefile.in
index c9e4294d3..b0293841a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -16,6 +16,7 @@ sysconfdir=@sysconfdir@
piddir=@piddir@
srcdir=@srcdir@
top_srcdir=@top_srcdir@
+abs_top_srcdir=@abs_top_srcdir@
DESTDIR=
VPATH=@srcdir@
@@ -49,7 +50,6 @@ PICFLAG=@PICFLAG@
LIBS=@LIBS@
K5LIBS=@K5LIBS@
GSSLIBS=@GSSLIBS@
-SSHLIBS=@SSHLIBS@
SSHDLIBS=@SSHDLIBS@
LIBEDIT=@LIBEDIT@
LIBFIDO2=@LIBFIDO2@
@@ -58,7 +58,6 @@ AWK=@AWK@
RANLIB=@RANLIB@
INSTALL=@INSTALL@
SED=@SED@
-ENT=@ENT@
XAUTH_PATH=@XAUTH_PATH@
LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
LDFLAGS_NOPIE=-L. -Lopenbsd-compat/ @LDFLAGS_NOPIE@
@@ -97,7 +96,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
cipher-ctr.o cleanup.o \
compat.o fatal.o hostfile.o \
log.o match.o moduli.o nchan.o packet.o \
- readpass.o ttymodes.o xmalloc.o addrmatch.o \
+ readpass.o ttymodes.o xmalloc.o addr.o addrmatch.o \
atomicio.o dispatch.o mac.o misc.o utf8.o \
monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-ecdsa-sk.o \
ssh-ed25519-sk.o ssh-rsa.o dh.o \
@@ -108,7 +107,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
hmac.o sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \
kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \
kexgexc.o kexgexs.o \
- sntrup4591761.o kexsntrup4591761x25519.o kexgen.o \
+ kexsntrup761x25519.o sntrup761.o kexgen.o \
sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \
sshbuf-io.o
@@ -127,12 +126,14 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \
monitor.o monitor_wrap.o auth-krb5.o \
auth2-gss.o gss-serv.o gss-serv-krb5.o \
loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \
- sftp-server.o sftp-common.o \
+ srclimit.o sftp-server.o sftp-common.o \
sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o \
sandbox-solaris.o uidswap.o $(SKOBJS)
-SCP_OBJS= scp.o progressmeter.o
+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)
@@ -150,7 +151,7 @@ SSHKEYSCAN_OBJS=ssh-keyscan.o $(SKOBJS)
SFTPSERVER_OBJS=sftp-common.o sftp-server.o sftp-server-main.o
-SFTP_OBJS= sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o
+SFTP_OBJS= sftp.o progressmeter.o $(SFTP_CLIENT_OBJS)
MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-sk-helper.8.out sshd_config.5.out ssh_config.5.out
MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-sk-helper.8 sshd_config.5 ssh_config.5
@@ -189,7 +190,7 @@ $(SSHOBJS): Makefile.in config.h
$(SSHDOBJS): Makefile.in config.h
configure-check: $(srcdir)/configure
-$(srcdir)/configure: configure.ac aclocal.m4
+$(srcdir)/configure: configure.ac $(srcdir)/m4/*.m4
@echo "ERROR: configure is out of date; please run ${AUTORECONF} (and configure)" 1>&2
@exit 1
@@ -206,7 +207,7 @@ libssh.a: $(LIBSSH_OBJS)
$(RANLIB) $@
ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS)
- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS) $(GSSLIBS)
+ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(GSSLIBS)
sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS)
$(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS)
@@ -236,7 +237,7 @@ ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS)
$(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a $(SFTPSERVER_OBJS)
- $(LD) -o $@ $(SFTPSERVER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
+ $(LD) -o $@ $(SFTPSERVER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
sftp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SFTP_OBJS)
$(LD) -o $@ $(SFTP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT)
@@ -273,10 +274,8 @@ clean: regressclean
rm -f regress/mkdtemp$(EXEEXT)
rm -f regress/unittests/test_helper/*.a
rm -f regress/unittests/test_helper/*.o
- rm -f regress/unittests/sshbuf/*.o
- rm -f regress/unittests/sshbuf/test_sshbuf$(EXEEXT)
- rm -f regress/unittests/sshkey/*.o
- rm -f regress/unittests/sshkey/test_sshkey$(EXEEXT)
+ rm -f regress/unittests/authopt/*.o
+ rm -f regress/unittests/authopt/test_authopt$(EXEEXT)
rm -f regress/unittests/bitmap/*.o
rm -f regress/unittests/bitmap/test_bitmap$(EXEEXT)
rm -f regress/unittests/conversion/*.o
@@ -287,10 +286,16 @@ clean: regressclean
rm -f regress/unittests/kex/test_kex$(EXEEXT)
rm -f regress/unittests/match/*.o
rm -f regress/unittests/match/test_match$(EXEEXT)
+ rm -f regress/unittests/misc/*.o
+ rm -f regress/unittests/misc/test_misc$(EXEEXT)
+ rm -f regress/unittests/sshbuf/*.o
+ rm -f regress/unittests/sshbuf/test_sshbuf$(EXEEXT)
+ rm -f regress/unittests/sshkey/*.o
+ rm -f regress/unittests/sshkey/test_sshkey$(EXEEXT)
+ rm -f regress/unittests/sshsig/*.o
+ rm -f regress/unittests/sshsig/test_sshsig$(EXEEXT)
rm -f regress/unittests/utf8/*.o
rm -f regress/unittests/utf8/test_utf8$(EXEEXT)
- rm -f regress/misc/kexfuzz/*.o
- rm -f regress/misc/kexfuzz/kexfuzz$(EXEEXT)
rm -f regress/misc/sk-dummy/*.o
rm -f regress/misc/sk-dummy/*.lo
rm -f regress/misc/sk-dummy/sk-dummy.so
@@ -306,10 +311,8 @@ distclean: regressclean
rm -f regress/mkdtemp
rm -f regress/unittests/test_helper/*.a
rm -f regress/unittests/test_helper/*.o
- rm -f regress/unittests/sshbuf/*.o
- rm -f regress/unittests/sshbuf/test_sshbuf
- rm -f regress/unittests/sshkey/*.o
- rm -f regress/unittests/sshkey/test_sshkey
+ rm -f regress/unittests/authopt/*.o
+ rm -f regress/unittests/authopt/test_authopt
rm -f regress/unittests/bitmap/*.o
rm -f regress/unittests/bitmap/test_bitmap
rm -f regress/unittests/conversion/*.o
@@ -320,10 +323,16 @@ distclean: regressclean
rm -f regress/unittests/kex/test_kex
rm -f regress/unittests/match/*.o
rm -f regress/unittests/match/test_match
+ rm -f regress/unittests/misc/*.o
+ rm -f regress/unittests/misc/test_misc
+ rm -f regress/unittests/sshbuf/*.o
+ rm -f regress/unittests/sshbuf/test_sshbuf
+ rm -f regress/unittests/sshkey/*.o
+ rm -f regress/unittests/sshkey/test_sshkey
+ rm -f regress/unittests/sshsig/*.o
+ rm -f regress/unittests/sshsig/test_sshsig
rm -f regress/unittests/utf8/*.o
rm -f regress/unittests/utf8/test_utf8
- rm -f regress/misc/kexfuzz/*.o
- rm -f regress/misc/kexfuzz/kexfuzz$(EXEEXT)
(cd openbsd-compat && $(MAKE) distclean)
if test -d pkg ; then \
rm -fr pkg ; \
@@ -486,15 +495,17 @@ uninstall:
regress-prep:
$(MKDIR_P) `pwd`/regress/unittests/test_helper
- $(MKDIR_P) `pwd`/regress/unittests/sshbuf
- $(MKDIR_P) `pwd`/regress/unittests/sshkey
+ $(MKDIR_P) `pwd`/regress/unittests/authopt
$(MKDIR_P) `pwd`/regress/unittests/bitmap
$(MKDIR_P) `pwd`/regress/unittests/conversion
$(MKDIR_P) `pwd`/regress/unittests/hostkeys
$(MKDIR_P) `pwd`/regress/unittests/kex
$(MKDIR_P) `pwd`/regress/unittests/match
+ $(MKDIR_P) `pwd`/regress/unittests/misc
+ $(MKDIR_P) `pwd`/regress/unittests/sshbuf
+ $(MKDIR_P) `pwd`/regress/unittests/sshkey
+ $(MKDIR_P) `pwd`/regress/unittests/sshsig
$(MKDIR_P) `pwd`/regress/unittests/utf8
- $(MKDIR_P) `pwd`/regress/misc/kexfuzz
$(MKDIR_P) `pwd`/regress/misc/sk-dummy
[ -f `pwd`/regress/Makefile ] || \
ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile
@@ -559,6 +570,17 @@ regress/unittests/sshkey/test_sshkey$(EXEEXT): ${UNITTESTS_TEST_SSHKEY_OBJS} \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
+UNITTESTS_TEST_SSHSIG_OBJS=\
+ sshsig.o \
+ regress/unittests/sshsig/tests.o \
+ $(SKOBJS)
+
+regress/unittests/sshsig/test_sshsig$(EXEEXT): ${UNITTESTS_TEST_SSHSIG_OBJS} \
+ regress/unittests/test_helper/libtest_helper.a libssh.a
+ $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_SSHSIG_OBJS) \
+ regress/unittests/test_helper/libtest_helper.a \
+ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
+
UNITTESTS_TEST_BITMAP_OBJS=\
regress/unittests/bitmap/tests.o
@@ -568,6 +590,18 @@ regress/unittests/bitmap/test_bitmap$(EXEEXT): ${UNITTESTS_TEST_BITMAP_OBJS} \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
+UNITTESTS_TEST_AUTHOPT_OBJS=\
+ regress/unittests/authopt/tests.o \
+ auth-options.o \
+ $(SKOBJS)
+
+regress/unittests/authopt/test_authopt$(EXEEXT): \
+ ${UNITTESTS_TEST_AUTHOPT_OBJS} \
+ regress/unittests/test_helper/libtest_helper.a libssh.a
+ $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_AUTHOPT_OBJS) \
+ regress/unittests/test_helper/libtest_helper.a \
+ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
+
UNITTESTS_TEST_CONVERSION_OBJS=\
regress/unittests/conversion/tests.o
@@ -611,6 +645,21 @@ regress/unittests/match/test_match$(EXEEXT): \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
+UNITTESTS_TEST_MISC_OBJS=\
+ regress/unittests/misc/tests.o \
+ regress/unittests/misc/test_parse.o \
+ regress/unittests/misc/test_expand.o \
+ regress/unittests/misc/test_convtime.o \
+ regress/unittests/misc/test_argv.o \
+ regress/unittests/misc/test_strdelim.o
+
+regress/unittests/misc/test_misc$(EXEEXT): \
+ ${UNITTESTS_TEST_MISC_OBJS} \
+ regress/unittests/test_helper/libtest_helper.a libssh.a
+ $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_MISC_OBJS) \
+ regress/unittests/test_helper/libtest_helper.a \
+ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
+
UNITTESTS_TEST_UTF8_OBJS=\
regress/unittests/utf8/tests.o
@@ -621,14 +670,6 @@ regress/unittests/utf8/test_utf8$(EXEEXT): \
regress/unittests/test_helper/libtest_helper.a \
-lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
-MISC_KEX_FUZZ_OBJS=\
- regress/misc/kexfuzz/kexfuzz.o \
- $(SKOBJS)
-
-regress/misc/kexfuzz/kexfuzz$(EXEEXT): ${MISC_KEX_FUZZ_OBJS} libssh.a
- $(LD) -o $@ $(LDFLAGS) $(MISC_KEX_FUZZ_OBJS) \
- -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
-
# These all need to be compiled -fPIC, so they are treated differently.
SK_DUMMY_OBJS=\
regress/misc/sk-dummy/sk-dummy.lo \
@@ -653,15 +694,17 @@ regress-binaries: regress-prep $(LIBCOMPAT) \
$(SK_DUMMY_LIBRARY)
regress-unit-binaries: regress-prep $(REGRESSLIBS) \
- regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \
- regress/unittests/sshkey/test_sshkey$(EXEEXT) \
+ regress/unittests/authopt/test_authopt$(EXEEXT) \
regress/unittests/bitmap/test_bitmap$(EXEEXT) \
regress/unittests/conversion/test_conversion$(EXEEXT) \
regress/unittests/hostkeys/test_hostkeys$(EXEEXT) \
regress/unittests/kex/test_kex$(EXEEXT) \
regress/unittests/match/test_match$(EXEEXT) \
- regress/unittests/utf8/test_utf8$(EXEEXT) \
- regress/misc/kexfuzz/kexfuzz$(EXEEXT)
+ regress/unittests/misc/test_misc$(EXEEXT) \
+ regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \
+ regress/unittests/sshkey/test_sshkey$(EXEEXT) \
+ regress/unittests/sshsig/test_sshsig$(EXEEXT) \
+ regress/unittests/utf8/test_utf8$(EXEEXT)
tests: file-tests t-exec interop-tests unit
echo all tests passed
@@ -672,6 +715,7 @@ unit: regress-unit-binaries
$(MAKE) \
.OBJDIR="$${BUILDDIR}/regress" \
.CURDIR="`pwd`" \
+ OBJ="$${BUILDDIR}/regress" \
$@ && echo $@ tests passed
interop-tests t-exec file-tests: regress-prep regress-binaries $(TARGETS)
@@ -698,6 +742,7 @@ interop-tests t-exec file-tests: regress-prep regress-binaries $(TARGETS)
TEST_SSH_PKCS11_HELPER="$${BUILDDIR}/ssh-pkcs11-helper" \
TEST_SSH_SK_HELPER="$${BUILDDIR}/ssh-sk-helper" \
TEST_SSH_SFTPSERVER="$${BUILDDIR}/sftp-server" \
+ TEST_SSH_MODULI_FILE="$(abs_top_srcdir)/moduli" \
TEST_SSH_PLINK="plink" \
TEST_SSH_PUTTYGEN="puttygen" \
TEST_SSH_CONCH="conch" \
diff --git a/PROTOCOL b/PROTOCOL
index c702fca45..3141cda6f 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -140,7 +140,7 @@ window space and may be sent even if no window space is available.
NB. due to certain broken SSH implementations aborting upon receipt
of this message (in contravention of RFC4254 section 5.4), this
message is only sent to OpenSSH peers (identified by banner).
-Other SSH implementations may be whitelisted to receive this message
+Other SSH implementations may be listed to receive this message
upon request.
2.2. connection: disallow additional sessions extension
@@ -169,7 +169,7 @@ Note that this is not a general defence against compromised clients
NB. due to certain broken SSH implementations aborting upon receipt
of this message, the no-more-sessions request is only sent to OpenSSH
servers (identified by banner). Other SSH implementations may be
-whitelisted to receive this message upon request.
+listed to receive this message upon request.
2.3. connection: Tunnel forward extension "tun@openssh.com"
@@ -292,6 +292,7 @@ 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
@@ -465,6 +466,84 @@ respond with a SSH_FXP_STATUS message.
This extension is advertised in the SSH_FXP_VERSION hello with version
"1".
+3.7. sftp: Extension request "lsetstat@openssh.com"
+
+This request is like the "setstat" command, but sets file attributes on
+symlinks. It is implemented as a SSH_FXP_EXTENDED request with the
+following format:
+
+ uint32 id
+ string "lsetstat@openssh.com"
+ string path
+ ATTRS attrs
+
+See the "setstat" command for more details.
+
+This extension is advertised in the SSH_FXP_VERSION hello with version
+"1".
+
+3.8. sftp: Extension request "limits@openssh.com"
+
+This request is used to determine various limits the server might impose.
+Clients should not attempt to exceed these limits as the server might sever
+the connection immediately.
+
+ uint32 id
+ string "limits@openssh.com"
+
+The server will respond with a SSH_FXP_EXTENDED_REPLY reply:
+
+ uint32 id
+ uint64 max-packet-length
+ uint64 max-read-length
+ uint64 max-write-length
+ uint64 max-open-handles
+
+The 'max-packet-length' applies to the total number of bytes in a
+single SFTP packet. Servers SHOULD set this at least to 34000.
+
+The 'max-read-length' is the largest length in a SSH_FXP_READ packet.
+Even if the client requests a larger size, servers will usually respond
+with a shorter SSH_FXP_DATA packet. Servers SHOULD set this at least to
+32768.
+
+The 'max-write-length' is the largest length in a SSH_FXP_WRITE packet
+the server will accept. Servers SHOULD set this at least to 32768.
+
+The 'max-open-handles' is the maximum number of active handles that the
+server allows (e.g. handles created by SSH_FXP_OPEN and SSH_FXP_OPENDIR
+packets). Servers MAY count internal file handles against this limit
+(e.g. system logging or stdout/stderr), so clients SHOULD NOT expect to
+open this many handles in practice.
+
+If the server doesn't enforce a specific limit, then the field may be
+set to 0. This implies the server relies on the OS to enforce limits
+(e.g. available memory or file handles), and such limits might be
+dynamic. The client SHOULD take care to not try to exceed reasonable
+limits.
+
+This extension is advertised in the SSH_FXP_VERSION hello with version
+"1".
+
+3.9. sftp: Extension request "expand-path@openssh.com"
+
+This request supports canonicalisation of relative paths and
+those that need tilde-expansion, i.e. "~", "~/..." and "~user/..."
+These paths are expanded using shell-like rules and the resultant
+path is canonicalised similarly to SSH2_FXP_REALPATH.
+
+It is implemented as a SSH_FXP_EXTENDED request with the following
+format:
+
+ uint32 id
+ string "expand-path@openssh.com"
+ string path
+
+Its reply is the same format as that of SSH2_FXP_REALPATH.
+
+This extension is advertised in the SSH_FXP_VERSION hello with version
+"1".
+
4. Miscellaneous changes
4.1 Public key format
@@ -496,4 +575,4 @@ OpenSSH's connection multiplexing uses messages as described in
PROTOCOL.mux over a Unix domain socket for communications between a
master instance and later clients.
-$OpenBSD: PROTOCOL,v 1.37 2020/02/21 00:04:43 dtucker Exp $
+$OpenBSD: PROTOCOL,v 1.42 2021/08/09 23:47:44 djm Exp $
diff --git a/PROTOCOL.agent b/PROTOCOL.agent
index da3381942..ed47146a3 100644
--- a/PROTOCOL.agent
+++ b/PROTOCOL.agent
@@ -1,5 +1,5 @@
This file used to contain a description of the SSH agent protocol
-implemented by OpenSSH. It has since been superseded by an Internet-
-draft that is available from:
+implemented by OpenSSH. It has since been superseded by
+https://tools.ietf.org/html/draft-miller-ssh-agent-04
-https://tools.ietf.org/html/draft-miller-ssh-agent-02
+$OpenBSD: PROTOCOL.agent,v 1.14 2020/10/06 07:12:04 dtucker Exp $
diff --git a/PROTOCOL.certkeys b/PROTOCOL.certkeys
index 1fce87006..68622e607 100644
--- a/PROTOCOL.certkeys
+++ b/PROTOCOL.certkeys
@@ -45,7 +45,7 @@ SHA-2 signatures (SHA-256 and SHA-512 respectively):
rsa-sha2-512-cert-v01@openssh.com
These RSA/SHA-2 types should not appear in keys at rest or transmitted
-on their wire, but do appear in a SSH_MSG_KEXINIT's host-key algorithms
+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.
@@ -159,12 +159,11 @@ p, q, g, y are the DSA parameters as described in FIPS-186-2.
curve and public key are respectively the ECDSA "[identifier]" and "Q"
defined in section 3.1 of RFC5656.
-pk is the encoded Ed25519 public key as defined by
-draft-josefsson-eddsa-ed25519-03.
+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
+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
@@ -217,13 +216,13 @@ signature is computed over all preceding fields from the initial string
up to, and including the signature key. Signatures are computed and
encoded according to the rules defined for the CA's public key algorithm
(RFC4253 section 6.6 for ssh-rsa and ssh-dss, RFC5656 for the ECDSA
-types), and draft-josefsson-eddsa-ed25519-03 for Ed25519.
+types, and RFC8032 for Ed25519).
Critical options
----------------
The critical options section of the certificate specifies zero or more
-options on the certificates validity. The format of this field
+options on the certificate's validity. The format of this field
is a sequence of zero or more tuples:
string name
@@ -234,7 +233,7 @@ sequence. Each named option may only appear once in a certificate.
The name field identifies the option and the data field encodes
option-specific information (see below). All options are
-"critical", if an implementation does not recognise a option
+"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
@@ -256,10 +255,18 @@ source-address string Comma-separated list of source addresses
for authentication. Addresses are
specified in CIDR format (nn.nn.nn.nn/nn
or hhhh::hhhh/nn).
- If this option is not present then
+ 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
----------
@@ -280,11 +287,11 @@ their data fields are:
Name Format Description
-----------------------------------------------------------------------------
-no-presence-required empty Flag indicating that signatures made
+no-touch-required empty Flag indicating that signatures made
with this certificate need not assert
- user presence. This option only make
- sense for the U2F/FIDO security key
- types that support this feature in
+ 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
@@ -298,7 +305,7 @@ permit-agent-forwarding empty Flag indicating that agent forwarding
permit-port-forwarding empty Flag indicating that port-forwarding
should be allowed. If this option is
- not present then no port forwarding will
+ not present, then no port forwarding will
be allowed.
permit-pty empty Flag indicating that PTY allocation
@@ -311,4 +318,4 @@ permit-user-rc empty Flag indicating that execution of
of this script will not be permitted if
this option is not present.
-$OpenBSD: PROTOCOL.certkeys,v 1.17 2019/11/25 00:57:51 djm Exp $
+$OpenBSD: PROTOCOL.certkeys,v 1.19 2021/06/05 13:47:00 naddy Exp $
diff --git a/PROTOCOL.key b/PROTOCOL.key
index 959bd7aee..38df268b6 100644
--- a/PROTOCOL.key
+++ b/PROTOCOL.key
@@ -35,9 +35,9 @@ of the cipher block size.
uint32 checkint
uint32 checkint
- string privatekey1
+ byte[] privatekey1
string comment1
- string privatekey2
+ byte[] privatekey2
string comment2
...
string privatekeyN
@@ -48,6 +48,9 @@ of the cipher block size.
...
char padlen % 255
+where each private key is encoded using the same rules as used for
+SSH agent.
+
Before the key is encrypted, a random integer is assigned
to both checkint fields so successful decryption can be
quickly checked by verifying that both checkint fields
@@ -65,4 +68,4 @@ For unencrypted keys the cipher "none" and the KDF "none"
are used with empty passphrases. The options if the KDF "none"
are the empty string.
-$OpenBSD: PROTOCOL.key,v 1.1 2013/12/06 13:34:54 markus Exp $
+$OpenBSD: PROTOCOL.key,v 1.2 2021/05/07 02:29:40 djm Exp $
diff --git a/PROTOCOL.sshsig b/PROTOCOL.sshsig
index 720e1f18a..78457ddfc 100644
--- a/PROTOCOL.sshsig
+++ b/PROTOCOL.sshsig
@@ -71,7 +71,7 @@ encoding rules for the chosen key type. For RSA signatures, the
signature algorithm must be "rsa-sha2-512" or "rsa-sha2-256" (i.e.
not the legacy RSA-SHA1 "ssh-rsa").
-This blob is encoded as a string using the RFC4243 encoding
+This blob is encoded as a string using the RFC4253 encoding
rules and base64 encoded to form the middle part of the
armored signature.
@@ -97,3 +97,4 @@ the reserved field if it is not empty.
The data is concatenated and passed to the SSH signing
function.
+$OpenBSD: PROTOCOL.sshsig,v 1.4 2020/08/31 00:17:41 djm Exp $
diff --git a/PROTOCOL.u2f b/PROTOCOL.u2f
index 917e669cd..f8ca56b11 100644
--- a/PROTOCOL.u2f
+++ b/PROTOCOL.u2f
@@ -39,6 +39,13 @@ the key handle be supplied for each signature operation. U2F tokens
primarily use ECDSA signatures in the NIST-P256 field, though the FIDO2
standard specifies additional key types, including one based on Ed25519.
+Use of U2F security keys does not automatically imply multi-factor
+authentication. From sshd's perspective, a security key constitutes a
+single factor of authentication, even if protected by a PIN or biometric
+authentication. To enable multi-factor authentication in ssh, please
+refer to the AuthenticationMethods option in sshd_config(5).
+
+
SSH U2F Key formats
-------------------
@@ -147,6 +154,16 @@ by trusted hardware before it will issue a certificate. To support this
case, OpenSSH optionally allows retaining the attestation information
at the time of key generation. It will take the following format:
+ string "ssh-sk-attest-v01"
+ string attestation certificate
+ string enrollment signature
+ string authenticator data (CBOR encoded)
+ uint32 reserved flags
+ string reserved string
+
+A previous version of this format, emitted prior to OpenSSH 8.4 omitted
+the authenticator data.
+
string "ssh-sk-attest-v00"
string attestation certificate
string enrollment signature
@@ -202,6 +219,32 @@ For Ed25519 keys the signature is encoded as:
byte flags
uint32 counter
+webauthn signatures
+-------------------
+
+The W3C/FIDO webauthn[1] standard defines a mechanism for a web browser to
+interact with FIDO authentication tokens. This standard builds upon the
+FIDO standards, but requires different signature contents to raw FIDO
+messages. OpenSSH supports ECDSA/p256 webauthn signatures through the
+"webauthn-sk-ecdsa-sha2-nistp256@openssh.com" signature algorithm.
+
+The wire encoding for a webauthn-sk-ecdsa-sha2-nistp256@openssh.com
+signature is similar to the sk-ecdsa-sha2-nistp256@openssh.com format:
+
+ string "webauthn-sk-ecdsa-sha2-nistp256@openssh.com"
+ string ecdsa_signature
+ byte flags
+ uint32 counter
+ string origin
+ string clientData
+ string extensions
+
+Where "origin" is the HTTP origin making the signature, "clientData" is
+the JSON-like structure signed by the browser and "extensions" are any
+extensions used in making the signature.
+
+[1] https://www.w3.org/TR/webauthn-2/
+
ssh-agent protocol extensions
-----------------------------
@@ -234,87 +277,15 @@ regress testing. For this reason, OpenSSH shall support a dynamically-
loaded middleware libraries to communicate with security keys, but offer
support for the common case of USB HID security keys internally.
-The middleware library need only expose a handful of functions:
-
- #define SSH_SK_VERSION_MAJOR 0x00050000 /* API version */
- #define SSH_SK_VERSION_MAJOR_MASK 0xffff0000
-
- /* Flags */
- #define SSH_SK_USER_PRESENCE_REQD 0x01
- #define SSH_SK_USER_VERIFICATION_REQD 0x04
- #define SSH_SK_RESIDENT_KEY 0x20
-
- /* Algs */
- #define SSH_SK_ECDSA 0x00
- #define SSH_SK_ED25519 0x01
-
- /* Error codes */
- #define SSH_SK_ERR_GENERAL -1
- #define SSH_SK_ERR_UNSUPPORTED -2
- #define SSH_SK_ERR_PIN_REQUIRED -3
- #define SSH_SK_ERR_DEVICE_NOT_FOUND -4
-
- struct sk_enroll_response {
- uint8_t *public_key;
- size_t public_key_len;
- uint8_t *key_handle;
- size_t key_handle_len;
- uint8_t *signature;
- size_t signature_len;
- uint8_t *attestation_cert;
- size_t attestation_cert_len;
- };
-
- struct sk_sign_response {
- uint8_t flags;
- uint32_t counter;
- uint8_t *sig_r;
- size_t sig_r_len;
- uint8_t *sig_s;
- size_t sig_s_len;
- };
-
- struct sk_resident_key {
- uint32_t alg;
- size_t slot;
- char *application;
- struct sk_enroll_response key;
- };
-
- struct sk_option {
- char *name;
- char *value;
- uint8_t important;
- };
-
- /* Return the version of the middleware API */
- uint32_t sk_api_version(void);
-
- /* Enroll a U2F key (private key generation) */
- int sk_enroll(uint32_t alg,
- const uint8_t *challenge, size_t challenge_len,
- const char *application, uint8_t flags, const char *pin,
- struct sk_option **options,
- struct sk_enroll_response **enroll_response);
-
- /* Sign a challenge */
- int sk_sign(uint32_t alg, const uint8_t *message, size_t message_len,
- const char *application,
- const uint8_t *key_handle, size_t key_handle_len,
- uint8_t flags, const char *pin, struct sk_option **options,
- struct sk_sign_response **sign_response);
-
- /* Enumerate all resident keys */
- int sk_load_resident_keys(const char *pin, struct sk_option **options,
- struct sk_resident_key ***rks, size_t *nrks);
-
-The SSH_SK_VERSION_MAJOR should be incremented for each incompatible
+The middleware library need only expose a handful of functions and
+numbers listed in sk-api.h. Included in the defined numbers is a
+SSH_SK_VERSION_MAJOR that should be incremented for each incompatible
API change.
-The options may be used to pass miscellaneous options to the middleware
-as a NULL-terminated array of pointers to struct sk_option. The middleware
-may ignore unsupported or unknown options unless the "important" flag is
-set, in which case it should return failure if an unsupported option is
+miscellaneous options may be passed to the middleware as a NULL-
+terminated array of pointers to struct sk_option. The middleware may
+ignore unsupported or unknown options unless the "required" flag is set,
+in which case it should return failure if an unsupported option is
requested.
At present the following options names are supported:
@@ -335,3 +306,4 @@ In OpenSSH, the middleware will be invoked by using a similar mechanism to
ssh-pkcs11-helper to provide address-space containment of the
middleware from ssh-agent.
+$OpenBSD: PROTOCOL.u2f,v 1.26 2020/09/09 03:08:01 djm Exp $
diff --git a/README b/README
index cae4c28c7..329aaeda2 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-See https://www.openssh.com/releasenotes.html#8.3p1 for the release notes.
+See https://www.openssh.com/releasenotes.html#8.8p1 for the release notes.
Please read https://www.openssh.com/report.html for bug reporting
instructions and note that we do not use Github for bug reporting or
diff --git a/README.md b/README.md
index 28fb43d2a..de4717737 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,6 @@
# Portable OpenSSH
+[![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)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/openssh.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:openssh)
OpenSSH is a complete implementation of the SSH protocol (version 2) for secure remote login, command execution and file transfer. It includes a client ``ssh`` and server ``sshd``, file transfer utilities ``scp`` and ``sftp`` as well as tools for key generation (``ssh-keygen``), run-time key storage (``ssh-agent``) and a number of supporting programs.
@@ -27,9 +28,13 @@ Stable release tarballs are available from a number of [download mirrors](https:
### Dependencies
-Portable OpenSSH is built using autoconf and make. It requires a working C compiler, standard library and headers, and [zlib](https://www.zlib.net/). ``libcrypto`` from either [LibreSSL](https://www.libressl.org/) or [OpenSSL](https://www.openssl.org) may also be used, but OpenSSH may be built without it supporting a subset of crypto algorithms.
+Portable OpenSSH is built using autoconf and make. It requires a working C compiler, standard library and headers.
-FIDO security token support need [libfido2](https://github.com/Yubico/libfido2) and its dependencies. Also, certain platforms and build-time options may require additional dependencies, see README.platform for details.
+``libcrypto`` from either [LibreSSL](https://www.libressl.org/) or [OpenSSL](https://www.openssl.org) may also be used, but OpenSSH may be built without it supporting a subset of crypto algorithms.
+
+[zlib](https://www.zlib.net/) is optional; without it transport compression is not supported.
+
+FIDO security token support needs [libfido2](https://github.com/Yubico/libfido2) and its dependencies. Also, certain platforms and build-time options may require additional dependencies; see README.platform for details.
### Building a release
@@ -43,7 +48,7 @@ make && make tests
```
See the [Build-time Customisation](#build-time-customisation) section below for configure options. If you plan on installing OpenSSH to your system, then you will usually want to specify destination paths.
-
+
### Building from git
If building from git, you'll need [autoconf](https://www.gnu.org/software/autoconf/) installed to build the ``configure`` script. The following commands will check out and build portable OpenSSH from git:
diff --git a/README.platform b/README.platform
index 9210e07c8..7b754ba42 100644
--- a/README.platform
+++ b/README.platform
@@ -1,19 +1,19 @@
This file contains notes about OpenSSH on specific platforms.
AIX
----
-As of OpenSSH 3.8p1, sshd will now honour an accounts password expiry
-settings, where previously it did not. Because of this, it's possible for
-sites that have used OpenSSH's sshd exclusively to have accounts which
-have passwords expired longer than the inactive time (ie the "Weeks between
-password EXPIRATION and LOCKOUT" setting in SMIT or the maxexpired
-chuser attribute).
+
+Beginning with OpenSSH 3.8p1, sshd will honour an account's password
+expiry settings, where prior to that it did not. Because of this,
+it's possible for sites that have used OpenSSH's sshd exclusively to
+have accounts which have passwords expired longer than the inactive time
+(ie the "Weeks between password EXPIRATION and LOCKOUT" setting in SMIT
+or the maxexpired chuser attribute).
Accounts in this state must have their passwords reset manually by the
administrator. As a precaution, it is recommended that the administrative
passwords be reset before upgrading from OpenSSH <3.8.
-As of OpenSSH 4.0, configure will attempt to detect if your version
+As of OpenSSH 4.0p1, configure will attempt to detect if your version
and maintenance level of AIX has a working getaddrinfo, and will use it
if found. This will enable IPv6 support. If for some reason configure
gets it wrong, or if you want to build binaries to work on earlier MLs
diff --git a/README.version b/README.version
index 030d77daf..02c1f0aa4 100644
--- a/README.version
+++ b/README.version
@@ -1,4 +1,4 @@
-URL: https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-8.3p1.tar.gz
-Version: 8.3p1
+URL: https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-8.8p1.tar.gz
+Version: 8.8p1
BugComponent: 180238
Owners: adelva, cloud-android-devs
diff --git a/addr.c b/addr.c
new file mode 100644
index 000000000..ba0fad4e9
--- /dev/null
+++ b/addr.c
@@ -0,0 +1,423 @@
+/* $OpenBSD: addr.c,v 1.1 2021/01/09 11:58:50 dtucker Exp $ */
+
+/*
+ * Copyright (c) 2004-2008 Damien Miller <djm@mindrot.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "addr.h"
+
+#define _SA(x) ((struct sockaddr *)(x))
+
+int
+addr_unicast_masklen(int af)
+{
+ switch (af) {
+ case AF_INET:
+ return 32;
+ case AF_INET6:
+ return 128;
+ default:
+ return -1;
+ }
+}
+
+static inline int
+masklen_valid(int af, u_int masklen)
+{
+ switch (af) {
+ case AF_INET:
+ return masklen <= 32 ? 0 : -1;
+ case AF_INET6:
+ return masklen <= 128 ? 0 : -1;
+ default:
+ return -1;
+ }
+}
+
+int
+addr_xaddr_to_sa(const struct xaddr *xa, struct sockaddr *sa, socklen_t *len,
+ u_int16_t port)
+{
+ struct sockaddr_in *in4 = (struct sockaddr_in *)sa;
+ struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
+
+ if (xa == NULL || sa == NULL || len == NULL)
+ return -1;
+
+ switch (xa->af) {
+ case AF_INET:
+ if (*len < sizeof(*in4))
+ return -1;
+ memset(sa, '\0', sizeof(*in4));
+ *len = sizeof(*in4);
+#ifdef SOCK_HAS_LEN
+ in4->sin_len = sizeof(*in4);
+#endif
+ in4->sin_family = AF_INET;
+ in4->sin_port = htons(port);
+ memcpy(&in4->sin_addr, &xa->v4, sizeof(in4->sin_addr));
+ break;
+ case AF_INET6:
+ if (*len < sizeof(*in6))
+ return -1;
+ memset(sa, '\0', sizeof(*in6));
+ *len = sizeof(*in6);
+#ifdef SOCK_HAS_LEN
+ in6->sin6_len = sizeof(*in6);
+#endif
+ in6->sin6_family = AF_INET6;
+ in6->sin6_port = htons(port);
+ memcpy(&in6->sin6_addr, &xa->v6, sizeof(in6->sin6_addr));
+#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
+ in6->sin6_scope_id = xa->scope_id;
+#endif
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Convert struct sockaddr to struct xaddr
+ * Returns 0 on success, -1 on failure.
+ */
+int
+addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa)
+{
+ struct sockaddr_in *in4 = (struct sockaddr_in *)sa;
+ struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
+
+ memset(xa, '\0', sizeof(*xa));
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ if (slen < (socklen_t)sizeof(*in4))
+ return -1;
+ xa->af = AF_INET;
+ memcpy(&xa->v4, &in4->sin_addr, sizeof(xa->v4));
+ break;
+ case AF_INET6:
+ if (slen < (socklen_t)sizeof(*in6))
+ return -1;
+ xa->af = AF_INET6;
+ memcpy(&xa->v6, &in6->sin6_addr, sizeof(xa->v6));
+#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
+ xa->scope_id = in6->sin6_scope_id;
+#endif
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+addr_invert(struct xaddr *n)
+{
+ int i;
+
+ if (n == NULL)
+ return -1;
+
+ switch (n->af) {
+ case AF_INET:
+ n->v4.s_addr = ~n->v4.s_addr;
+ return 0;
+ case AF_INET6:
+ for (i = 0; i < 4; i++)
+ n->addr32[i] = ~n->addr32[i];
+ return 0;
+ default:
+ return -1;
+ }
+}
+
+/*
+ * Calculate a netmask of length 'l' for address family 'af' and
+ * store it in 'n'.
+ * Returns 0 on success, -1 on failure.
+ */
+int
+addr_netmask(int af, u_int l, struct xaddr *n)
+{
+ int i;
+
+ if (masklen_valid(af, l) != 0 || n == NULL)
+ return -1;
+
+ memset(n, '\0', sizeof(*n));
+ switch (af) {
+ case AF_INET:
+ n->af = AF_INET;
+ if (l == 0)
+ return 0;
+ n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff);
+ return 0;
+ case AF_INET6:
+ n->af = AF_INET6;
+ for (i = 0; i < 4 && l >= 32; i++, l -= 32)
+ n->addr32[i] = 0xffffffffU;
+ if (i < 4 && l != 0)
+ n->addr32[i] = htonl((0xffffffff << (32 - l)) &
+ 0xffffffff);
+ return 0;
+ default:
+ return -1;
+ }
+}
+
+int
+addr_hostmask(int af, u_int l, struct xaddr *n)
+{
+ if (addr_netmask(af, l, n) == -1 || addr_invert(n) == -1)
+ return -1;
+ return 0;
+}
+
+/*
+ * Perform logical AND of addresses 'a' and 'b', storing result in 'dst'.
+ * Returns 0 on success, -1 on failure.
+ */
+int
+addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b)
+{
+ int i;
+
+ if (dst == NULL || a == NULL || b == NULL || a->af != b->af)
+ return -1;
+
+ memcpy(dst, a, sizeof(*dst));
+ switch (a->af) {
+ case AF_INET:
+ dst->v4.s_addr &= b->v4.s_addr;
+ return 0;
+ case AF_INET6:
+ dst->scope_id = a->scope_id;
+ for (i = 0; i < 4; i++)
+ dst->addr32[i] &= b->addr32[i];
+ return 0;
+ default:
+ return -1;
+ }
+}
+
+int
+addr_cmp(const struct xaddr *a, const struct xaddr *b)
+{
+ int i;
+
+ if (a->af != b->af)
+ return (a->af == AF_INET6 ? 1 : -1);
+
+ switch (a->af) {
+ case AF_INET:
+ /*
+ * Can't just subtract here as 255.255.255.255 - 0.0.0.0 is
+ * too big to fit into a signed int
+ */
+ if (a->v4.s_addr == b->v4.s_addr)
+ return 0;
+ return (ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr) ? 1 : -1);
+ case AF_INET6:;
+ /*
+ * Do this a byte at a time to avoid the above issue and
+ * any endian problems
+ */
+ for (i = 0; i < 16; i++)
+ if (a->addr8[i] - b->addr8[i] != 0)
+ return (a->addr8[i] - b->addr8[i]);
+ if (a->scope_id == b->scope_id)
+ return (0);
+ return (a->scope_id > b->scope_id ? 1 : -1);
+ default:
+ return (-1);
+ }
+}
+
+int
+addr_is_all0s(const struct xaddr *a)
+{
+ int i;
+
+ switch (a->af) {
+ case AF_INET:
+ return (a->v4.s_addr == 0 ? 0 : -1);
+ case AF_INET6:;
+ for (i = 0; i < 4; i++)
+ if (a->addr32[i] != 0)
+ return -1;
+ return 0;
+ default:
+ return -1;
+ }
+}
+
+/*
+ * Test whether host portion of address 'a', as determined by 'masklen'
+ * is all zeros.
+ * Returns 0 on if host portion of address is all-zeros,
+ * -1 if not all zeros or on failure.
+ */
+int
+addr_host_is_all0s(const struct xaddr *a, u_int masklen)
+{
+ struct xaddr tmp_addr, tmp_mask, tmp_result;
+
+ memcpy(&tmp_addr, a, sizeof(tmp_addr));
+ if (addr_hostmask(a->af, masklen, &tmp_mask) == -1)
+ return -1;
+ if (addr_and(&tmp_result, &tmp_addr, &tmp_mask) == -1)
+ return -1;
+ return addr_is_all0s(&tmp_result);
+}
+
+/*
+ * Parse string address 'p' into 'n'
+ * Returns 0 on success, -1 on failure.
+ */
+int
+addr_pton(const char *p, struct xaddr *n)
+{
+ struct addrinfo hints, *ai;
+
+ memset(&hints, '\0', sizeof(hints));
+ hints.ai_flags = AI_NUMERICHOST;
+
+ if (p == NULL || getaddrinfo(p, NULL, &hints, &ai) != 0)
+ return -1;
+
+ if (ai == NULL || ai->ai_addr == NULL)
+ return -1;
+
+ if (n != NULL && addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen,
+ n) == -1) {
+ freeaddrinfo(ai);
+ return -1;
+ }
+
+ freeaddrinfo(ai);
+ return 0;
+}
+
+int
+addr_sa_pton(const char *h, const char *s, struct sockaddr *sa, socklen_t slen)
+{
+ struct addrinfo hints, *ai;
+
+ memset(&hints, '\0', sizeof(hints));
+ hints.ai_flags = AI_NUMERICHOST;
+
+ if (h == NULL || getaddrinfo(h, s, &hints, &ai) != 0)
+ return -1;
+
+ if (ai == NULL || ai->ai_addr == NULL)
+ return -1;
+
+ if (sa != NULL) {
+ if (slen < ai->ai_addrlen)
+ return -1;
+ memcpy(sa, &ai->ai_addr, ai->ai_addrlen);
+ }
+
+ freeaddrinfo(ai);
+ return 0;
+}
+
+int
+addr_ntop(const struct xaddr *n, char *p, size_t len)
+{
+ struct sockaddr_storage ss;
+ socklen_t slen = sizeof(ss);
+
+ if (addr_xaddr_to_sa(n, _SA(&ss), &slen, 0) == -1)
+ return -1;
+ if (n == NULL || p == NULL || len == 0)
+ return -1;
+ if (getnameinfo(_SA(&ss), slen, p, len, NULL, 0,
+ NI_NUMERICHOST) == -1)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * Parse a CIDR address (x.x.x.x/y or xxxx:yyyy::/z).
+ * Return -1 on parse error, -2 on inconsistency or 0 on success.
+ */
+int
+addr_pton_cidr(const char *p, struct xaddr *n, u_int *l)
+{
+ struct xaddr tmp;
+ long unsigned int masklen = 999;
+ char addrbuf[64], *mp, *cp;
+
+ /* Don't modify argument */
+ if (p == NULL || strlcpy(addrbuf, p, sizeof(addrbuf)) >= sizeof(addrbuf))
+ return -1;
+
+ if ((mp = strchr(addrbuf, '/')) != NULL) {
+ *mp = '\0';
+ mp++;
+ masklen = strtoul(mp, &cp, 10);
+ if (*mp == '\0' || *cp != '\0' || masklen > 128)
+ return -1;
+ }
+
+ if (addr_pton(addrbuf, &tmp) == -1)
+ return -1;
+
+ if (mp == NULL)
+ masklen = addr_unicast_masklen(tmp.af);
+ if (masklen_valid(tmp.af, masklen) == -1)
+ return -2;
+ if (addr_host_is_all0s(&tmp, masklen) != 0)
+ return -2;
+
+ if (n != NULL)
+ memcpy(n, &tmp, sizeof(*n));
+ if (l != NULL)
+ *l = masklen;
+
+ return 0;
+}
+
+int
+addr_netmatch(const struct xaddr *host, const struct xaddr *net, u_int masklen)
+{
+ struct xaddr tmp_mask, tmp_result;
+
+ if (host->af != net->af)
+ return -1;
+
+ if (addr_netmask(host->af, masklen, &tmp_mask) == -1)
+ return -1;
+ if (addr_and(&tmp_result, host, &tmp_mask) == -1)
+ return -1;
+ return addr_cmp(&tmp_result, net);
+}
diff --git a/addr.h b/addr.h
new file mode 100644
index 000000000..5eff02628
--- /dev/null
+++ b/addr.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2004,2005 Damien Miller <djm@mindrot.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* Address handling routines */
+
+#ifndef _ADDR_H
+#define _ADDR_H
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+struct xaddr {
+ sa_family_t af;
+ union {
+ struct in_addr v4;
+ struct in6_addr v6;
+ u_int8_t addr8[16];
+ u_int16_t addr16[8];
+ u_int32_t addr32[4];
+ } xa; /* 128-bit address */
+ u_int32_t scope_id; /* iface scope id for v6 */
+#define v4 xa.v4
+#define v6 xa.v6
+#define addr8 xa.addr8
+#define addr16 xa.addr16
+#define addr32 xa.addr32
+};
+
+int addr_unicast_masklen(int af);
+int addr_xaddr_to_sa(const struct xaddr *xa, struct sockaddr *sa,
+ socklen_t *len, u_int16_t port);
+int addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa);
+int addr_netmask(int af, u_int l, struct xaddr *n);
+int addr_hostmask(int af, u_int l, struct xaddr *n);
+int addr_invert(struct xaddr *n);
+int addr_pton(const char *p, struct xaddr *n);
+int addr_sa_pton(const char *h, const char *s, struct sockaddr *sa,
+ socklen_t slen);
+int addr_pton_cidr(const char *p, struct xaddr *n, u_int *l);
+int addr_ntop(const struct xaddr *n, char *p, size_t len);
+int addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b);
+int addr_cmp(const struct xaddr *a, const struct xaddr *b);
+int addr_is_all0s(const struct xaddr *n);
+int addr_host_is_all0s(const struct xaddr *n, u_int masklen);
+int addr_netmatch(const struct xaddr *host, const struct xaddr *net,
+ u_int masklen);
+#endif /* _ADDR_H */
diff --git a/addrmatch.c b/addrmatch.c
index 5a402d065..b0dc09680 100644
--- a/addrmatch.c
+++ b/addrmatch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: addrmatch.c,v 1.14 2018/07/31 03:07:24 djm Exp $ */
+/* $OpenBSD: addrmatch.c,v 1.17 2021/04/03 06:18:40 djm Exp $ */
/*
* Copyright (c) 2004-2008 Damien Miller <djm@mindrot.org>
@@ -29,337 +29,10 @@
#include <stdio.h>
#include <stdarg.h>
+#include "addr.h"
#include "match.h"
#include "log.h"
-struct xaddr {
- sa_family_t af;
- union {
- struct in_addr v4;
- struct in6_addr v6;
- u_int8_t addr8[16];
- u_int32_t addr32[4];
- } xa; /* 128-bit address */
- u_int32_t scope_id; /* iface scope id for v6 */
-#define v4 xa.v4
-#define v6 xa.v6
-#define addr8 xa.addr8
-#define addr32 xa.addr32
-};
-
-static int
-addr_unicast_masklen(int af)
-{
- switch (af) {
- case AF_INET:
- return 32;
- case AF_INET6:
- return 128;
- default:
- return -1;
- }
-}
-
-static inline int
-masklen_valid(int af, u_int masklen)
-{
- switch (af) {
- case AF_INET:
- return masklen <= 32 ? 0 : -1;
- case AF_INET6:
- return masklen <= 128 ? 0 : -1;
- default:
- return -1;
- }
-}
-
-/*
- * Convert struct sockaddr to struct xaddr
- * Returns 0 on success, -1 on failure.
- */
-static int
-addr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa)
-{
- struct sockaddr_in *in4 = (struct sockaddr_in *)sa;
- struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
-
- memset(xa, '\0', sizeof(*xa));
-
- switch (sa->sa_family) {
- case AF_INET:
- if (slen < (socklen_t)sizeof(*in4))
- return -1;
- xa->af = AF_INET;
- memcpy(&xa->v4, &in4->sin_addr, sizeof(xa->v4));
- break;
- case AF_INET6:
- if (slen < (socklen_t)sizeof(*in6))
- return -1;
- xa->af = AF_INET6;
- memcpy(&xa->v6, &in6->sin6_addr, sizeof(xa->v6));
-#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
- xa->scope_id = in6->sin6_scope_id;
-#endif
- break;
- default:
- return -1;
- }
-
- return 0;
-}
-
-/*
- * Calculate a netmask of length 'l' for address family 'af' and
- * store it in 'n'.
- * Returns 0 on success, -1 on failure.
- */
-static int
-addr_netmask(int af, u_int l, struct xaddr *n)
-{
- int i;
-
- if (masklen_valid(af, l) != 0 || n == NULL)
- return -1;
-
- memset(n, '\0', sizeof(*n));
- switch (af) {
- case AF_INET:
- n->af = AF_INET;
- if (l == 0)
- return 0;
- n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff);
- return 0;
- case AF_INET6:
- n->af = AF_INET6;
- for (i = 0; i < 4 && l >= 32; i++, l -= 32)
- n->addr32[i] = 0xffffffffU;
- if (i < 4 && l != 0)
- n->addr32[i] = htonl((0xffffffff << (32 - l)) &
- 0xffffffff);
- return 0;
- default:
- return -1;
- }
-}
-
-/*
- * Perform logical AND of addresses 'a' and 'b', storing result in 'dst'.
- * Returns 0 on success, -1 on failure.
- */
-static int
-addr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b)
-{
- int i;
-
- if (dst == NULL || a == NULL || b == NULL || a->af != b->af)
- return -1;
-
- memcpy(dst, a, sizeof(*dst));
- switch (a->af) {
- case AF_INET:
- dst->v4.s_addr &= b->v4.s_addr;
- return 0;
- case AF_INET6:
- dst->scope_id = a->scope_id;
- for (i = 0; i < 4; i++)
- dst->addr32[i] &= b->addr32[i];
- return 0;
- default:
- return -1;
- }
-}
-
-/*
- * Compare addresses 'a' and 'b'
- * Return 0 if addresses are identical, -1 if (a < b) or 1 if (a > b)
- */
-static int
-addr_cmp(const struct xaddr *a, const struct xaddr *b)
-{
- int i;
-
- if (a->af != b->af)
- return a->af == AF_INET6 ? 1 : -1;
-
- switch (a->af) {
- case AF_INET:
- if (a->v4.s_addr == b->v4.s_addr)
- return 0;
- return ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr) ? 1 : -1;
- case AF_INET6:
- for (i = 0; i < 16; i++)
- if (a->addr8[i] - b->addr8[i] != 0)
- return a->addr8[i] > b->addr8[i] ? 1 : -1;
- if (a->scope_id == b->scope_id)
- return 0;
- return a->scope_id > b->scope_id ? 1 : -1;
- default:
- return -1;
- }
-}
-
-/*
- * Parse string address 'p' into 'n'
- * Returns 0 on success, -1 on failure.
- */
-static int
-addr_pton(const char *p, struct xaddr *n)
-{
- struct addrinfo hints, *ai = NULL;
- int ret = -1;
-
- memset(&hints, '\0', sizeof(hints));
- hints.ai_flags = AI_NUMERICHOST;
-
- if (p == NULL || getaddrinfo(p, NULL, &hints, &ai) != 0)
- goto out;
- if (ai == NULL || ai->ai_addr == NULL)
- goto out;
- if (n != NULL && addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen, n) == -1)
- goto out;
- /* success */
- ret = 0;
- out:
- if (ai != NULL)
- freeaddrinfo(ai);
- return ret;
-}
-
-/*
- * Perform bitwise negation of address
- * Returns 0 on success, -1 on failure.
- */
-static int
-addr_invert(struct xaddr *n)
-{
- int i;
-
- if (n == NULL)
- return (-1);
-
- switch (n->af) {
- case AF_INET:
- n->v4.s_addr = ~n->v4.s_addr;
- return (0);
- case AF_INET6:
- for (i = 0; i < 4; i++)
- n->addr32[i] = ~n->addr32[i];
- return (0);
- default:
- return (-1);
- }
-}
-
-/*
- * Calculate a netmask of length 'l' for address family 'af' and
- * store it in 'n'.
- * Returns 0 on success, -1 on failure.
- */
-static int
-addr_hostmask(int af, u_int l, struct xaddr *n)
-{
- if (addr_netmask(af, l, n) == -1 || addr_invert(n) == -1)
- return (-1);
- return (0);
-}
-
-/*
- * Test whether address 'a' is all zeros (i.e. 0.0.0.0 or ::)
- * Returns 0 on if address is all-zeros, -1 if not all zeros or on failure.
- */
-static int
-addr_is_all0s(const struct xaddr *a)
-{
- int i;
-
- switch (a->af) {
- case AF_INET:
- return (a->v4.s_addr == 0 ? 0 : -1);
- case AF_INET6:;
- for (i = 0; i < 4; i++)
- if (a->addr32[i] != 0)
- return (-1);
- return (0);
- default:
- return (-1);
- }
-}
-
-/*
- * Test whether host portion of address 'a', as determined by 'masklen'
- * is all zeros.
- * Returns 0 on if host portion of address is all-zeros,
- * -1 if not all zeros or on failure.
- */
-static int
-addr_host_is_all0s(const struct xaddr *a, u_int masklen)
-{
- struct xaddr tmp_addr, tmp_mask, tmp_result;
-
- memcpy(&tmp_addr, a, sizeof(tmp_addr));
- if (addr_hostmask(a->af, masklen, &tmp_mask) == -1)
- return (-1);
- if (addr_and(&tmp_result, &tmp_addr, &tmp_mask) == -1)
- return (-1);
- return (addr_is_all0s(&tmp_result));
-}
-
-/*
- * Parse a CIDR address (x.x.x.x/y or xxxx:yyyy::/z).
- * Return -1 on parse error, -2 on inconsistency or 0 on success.
- */
-static int
-addr_pton_cidr(const char *p, struct xaddr *n, u_int *l)
-{
- struct xaddr tmp;
- long unsigned int masklen = 999;
- char addrbuf[64], *mp, *cp;
-
- /* Don't modify argument */
- if (p == NULL || strlcpy(addrbuf, p, sizeof(addrbuf)) >= sizeof(addrbuf))
- return -1;
-
- if ((mp = strchr(addrbuf, '/')) != NULL) {
- *mp = '\0';
- mp++;
- masklen = strtoul(mp, &cp, 10);
- if (*mp == '\0' || *cp != '\0' || masklen > 128)
- return -1;
- }
-
- if (addr_pton(addrbuf, &tmp) == -1)
- return -1;
-
- if (mp == NULL)
- masklen = addr_unicast_masklen(tmp.af);
- if (masklen_valid(tmp.af, masklen) == -1)
- return -2;
- if (addr_host_is_all0s(&tmp, masklen) != 0)
- return -2;
-
- if (n != NULL)
- memcpy(n, &tmp, sizeof(*n));
- if (l != NULL)
- *l = masklen;
-
- return 0;
-}
-
-static int
-addr_netmatch(const struct xaddr *host, const struct xaddr *net, u_int masklen)
-{
- struct xaddr tmp_mask, tmp_result;
-
- if (host->af != net->af)
- return -1;
-
- if (addr_netmask(host->af, masklen, &tmp_mask) == -1)
- return -1;
- if (addr_and(&tmp_result, host, &tmp_mask) == -1)
- return -1;
- return addr_cmp(&tmp_result, net);
-}
-
/*
* Match "addr" against list pattern list "_list", which may contain a
* mix of CIDR addresses and old-school wildcards.
@@ -381,7 +54,7 @@ addr_match_list(const char *addr, const char *_list)
int ret = 0, r;
if (addr != NULL && addr_pton(addr, &try_addr) != 0) {
- debug2("%s: couldn't parse address %.100s", __func__, addr);
+ debug2_f("couldn't parse address %.100s", addr);
return 0;
}
if ((o = list = strdup(_list)) == NULL)
@@ -397,13 +70,13 @@ addr_match_list(const char *addr, const char *_list)
/* Prefer CIDR address matching */
r = addr_pton_cidr(cp, &match_addr, &masklen);
if (r == -2) {
- debug2("%s: inconsistent mask length for "
- "match network \"%.100s\"", __func__, cp);
+ debug2_f("inconsistent mask length for "
+ "match network \"%.100s\"", cp);
ret = -2;
break;
} else if (r == 0) {
if (addr != NULL && addr_netmatch(&try_addr,
- &match_addr, masklen) == 0) {
+ &match_addr, masklen) == 0) {
foundit:
if (neg) {
ret = -1;
@@ -441,15 +114,14 @@ addr_match_cidr_list(const char *addr, const char *_list)
int ret = 0, r;
if (addr != NULL && addr_pton(addr, &try_addr) != 0) {
- debug2("%s: couldn't parse address %.100s", __func__, addr);
+ debug2_f("couldn't parse address %.100s", addr);
return 0;
}
if ((o = list = strdup(_list)) == NULL)
return -1;
while ((cp = strsep(&list, ",")) != NULL) {
if (*cp == '\0') {
- error("%s: empty entry in list \"%.100s\"",
- __func__, o);
+ error_f("empty entry in list \"%.100s\"", o);
ret = -1;
break;
}
@@ -462,15 +134,14 @@ addr_match_cidr_list(const char *addr, const char *_list)
/* Stop junk from reaching getaddrinfo. +3 is for masklen */
if (strlen(cp) > INET6_ADDRSTRLEN + 3) {
- error("%s: list entry \"%.100s\" too long",
- __func__, cp);
+ error_f("list entry \"%.100s\" too long", cp);
ret = -1;
break;
}
#define VALID_CIDR_CHARS "0123456789abcdefABCDEF.:/"
if (strspn(cp, VALID_CIDR_CHARS) != strlen(cp)) {
- error("%s: list entry \"%.100s\" contains invalid "
- "characters", __func__, cp);
+ error_f("list entry \"%.100s\" contains invalid "
+ "characters", cp);
ret = -1;
}
diff --git a/audit-bsm.c b/audit-bsm.c
index 0ba16c72c..ccfcf6f7f 100644
--- a/audit-bsm.c
+++ b/audit-bsm.c
@@ -129,7 +129,7 @@ static AuditInfoTermID ssh_bsm_tid;
* getaudit_addr() is only present on IPv6 capable machines.
*/
#if defined(HAVE_AUG_GET_MACHINE) || !defined(HAVE_GETAUDIT_ADDR)
-extern int aug_get_machine(char *, u_int32_t *, u_int32_t *);
+extern int aug_get_machine(char *, u_int32_t *, u_int32_t *);
#else
static int
aug_get_machine(char *host, u_int32_t *addr, u_int32_t *type)
@@ -183,41 +183,41 @@ getacna(char *auditstring, int len)
scf_value_t *value = NULL;
int ret = 0;
+ /*
+ * The man page for getacna on Solaris 10 states we should return -2
+ * in case of error and set errno to indicate the error. We don't
+ * bother with errno here, though, since the only use of this function
+ * below doesn't check for errors anyway.
+ */
handle = scf_handle_create(SCF_VERSION);
if (handle == NULL)
- return -2; /* The man page for getacna on Solaris 10 states
- we should return -2 in case of error and set
- errno to indicate the error. We don't bother
- with errno here, though, since the only use
- of this function below doesn't check for errors
- anyway.
- */
+ return -2;
ret = scf_handle_bind(handle);
if (ret == -1)
- return -2;
+ return -2;
property = scf_property_create(handle);
if (property == NULL)
- return -2;
+ return -2;
ret = scf_handle_decode_fmri(handle,
- "svc:/system/auditd:default/:properties/preselection/naflags",
- NULL, NULL, NULL, NULL, property, 0);
+ "svc:/system/auditd:default/:properties/preselection/naflags",
+ NULL, NULL, NULL, NULL, property, 0);
if (ret == -1)
- return -2;
+ return -2;
value = scf_value_create(handle);
if (value == NULL)
- return -2;
+ return -2;
ret = scf_property_get_value(property, value);
if (ret == -1)
- return -2;
+ return -2;
ret = scf_value_get_astring(value, auditstring, len);
if (ret == -1)
- return -2;
+ return -2;
scf_value_destroy(value);
scf_property_destroy(property);
@@ -280,9 +280,10 @@ bsm_audit_record(int typ, char *string, au_event_t event_no)
(void) au_write(ad, AUToReturnFunc(typ, rc));
#ifdef BROKEN_BSM_API
- /* The last argument is the event modifier flags. For
- some seemingly undocumented reason it was added in
- Solaris 11. */
+ /*
+ * The last argument is the event modifier flags. For some seemingly
+ * undocumented reason it was added in Solaris 11.
+ */
rc = au_close(ad, AU_TO_WRITE, event_no, 0);
#else
rc = au_close(ad, AU_TO_WRITE, event_no);
diff --git a/auth-krb5.c b/auth-krb5.c
index 3096f1c8e..c99e4e430 100644
--- a/auth-krb5.c
+++ b/auth-krb5.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-krb5.c,v 1.23 2018/07/09 21:35:50 markus Exp $ */
+/* $OpenBSD: auth-krb5.c,v 1.24 2021/04/03 06:18:40 djm Exp $ */
/*
* Kerberos v5 authentication and ticket-passing routines.
*
@@ -99,7 +99,7 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
#ifdef HEIMDAL
# ifdef HAVE_KRB5_CC_NEW_UNIQUE
problem = krb5_cc_new_unique(authctxt->krb5_ctx,
- krb5_mcc_ops.prefix, NULL, &ccache);
+ krb5_mcc_ops.prefix, NULL, &ccache);
# else
problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_mcc_ops, &ccache);
# endif
@@ -123,7 +123,7 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
# ifdef HAVE_KRB5_CC_NEW_UNIQUE
problem = krb5_cc_new_unique(authctxt->krb5_ctx,
- krb5_fcc_ops.prefix, NULL, &authctxt->krb5_fwd_ccache);
+ krb5_fcc_ops.prefix, NULL, &authctxt->krb5_fwd_ccache);
# else
problem = krb5_cc_gen_new(authctxt->krb5_ctx, &krb5_fcc_ops,
&authctxt->krb5_fwd_ccache);
@@ -163,17 +163,18 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
goto out;
}
- problem = ssh_krb5_cc_gen(authctxt->krb5_ctx, &authctxt->krb5_fwd_ccache);
+ problem = ssh_krb5_cc_gen(authctxt->krb5_ctx,
+ &authctxt->krb5_fwd_ccache);
if (problem)
goto out;
- problem = krb5_cc_initialize(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
- authctxt->krb5_user);
+ problem = krb5_cc_initialize(authctxt->krb5_ctx,
+ authctxt->krb5_fwd_ccache, authctxt->krb5_user);
if (problem)
goto out;
- problem= krb5_cc_store_cred(authctxt->krb5_ctx, authctxt->krb5_fwd_ccache,
- &creds);
+ problem = krb5_cc_store_cred(authctxt->krb5_ctx,
+ authctxt->krb5_fwd_ccache, &creds);
if (problem)
goto out;
#endif
@@ -202,7 +203,7 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
if (authctxt->krb5_ctx != NULL && problem!=-1) {
errmsg = krb5_get_error_message(authctxt->krb5_ctx,
problem);
- debug("Kerberos password authentication failed: %s",
+ debug("Kerberos password authentication failed: %s",
errmsg);
krb5_free_error_message(authctxt->krb5_ctx, errmsg);
} else
diff --git a/auth-options.c b/auth-options.c
index 696ba6ac6..335f03238 100644
--- a/auth-options.c
+++ b/auth-options.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-options.c,v 1.92 2020/03/06 18:15:38 markus Exp $ */
+/* $OpenBSD: auth-options.c,v 1.97 2021/07/24 01:55:19 djm Exp $ */
/*
* Copyright (c) 2018 Damien Miller <djm@mindrot.org>
*
@@ -79,7 +79,7 @@ cert_option_list(struct sshauthopt *opts, struct sshbuf *oblob,
int r, ret = -1, found;
if ((c = sshbuf_fromb(oblob)) == NULL) {
- error("%s: sshbuf_fromb failed", __func__);
+ error_f("sshbuf_fromb failed");
goto out;
}
@@ -88,8 +88,7 @@ cert_option_list(struct sshauthopt *opts, struct sshbuf *oblob,
data = NULL;
if ((r = sshbuf_get_cstring(c, &name, NULL)) != 0 ||
(r = sshbuf_froms(c, &data)) != 0) {
- error("Unable to parse certificate options: %s",
- ssh_err(r));
+ error_r(r, "Unable to parse certificate options");
goto out;
}
debug3("found certificate option \"%.100s\" len %zu",
@@ -119,11 +118,14 @@ cert_option_list(struct sshauthopt *opts, struct sshbuf *oblob,
}
}
if (!found && (which & OPTIONS_CRITICAL) != 0) {
- if (strcmp(name, "force-command") == 0) {
+ if (strcmp(name, "verify-required") == 0) {
+ opts->require_verify = 1;
+ found = 1;
+ } else if (strcmp(name, "force-command") == 0) {
if ((r = sshbuf_get_cstring(data, &command,
NULL)) != 0) {
- error("Unable to parse \"%s\" "
- "section: %s", name, ssh_err(r));
+ error_r(r, "Unable to parse \"%s\" "
+ "section", name);
goto out;
}
if (opts->force_command != NULL) {
@@ -134,12 +136,11 @@ cert_option_list(struct sshauthopt *opts, struct sshbuf *oblob,
}
opts->force_command = command;
found = 1;
- }
- if (strcmp(name, "source-address") == 0) {
+ } else if (strcmp(name, "source-address") == 0) {
if ((r = sshbuf_get_cstring(data, &allowed,
NULL)) != 0) {
- error("Unable to parse \"%s\" "
- "section: %s", name, ssh_err(r));
+ error_r(r, "Unable to parse \"%s\" "
+ "section", name);
goto out;
}
if (opts->required_from_host_cert != NULL) {
@@ -323,6 +324,7 @@ sshauthopt_parse(const char *opts, const char **errstrp)
struct sshauthopt *ret = NULL;
const char *errstr = "unknown error";
uint64_t valid_before;
+ size_t i, l;
if (errstrp != NULL)
*errstrp = NULL;
@@ -351,6 +353,8 @@ sshauthopt_parse(const char *opts, const char **errstrp)
ret->permit_x11_forwarding_flag = r == 1;
} else if ((r = opt_flag("touch-required", 1, &opts)) != -1) {
ret->no_require_user_presence = r != 1; /* NB. flip */
+ } else if ((r = opt_flag("verify-required", 1, &opts)) != -1) {
+ ret->require_verify = r == 1;
} else if ((r = opt_flag("pty", 1, &opts)) != -1) {
ret->permit_pty_flag = r == 1;
} else if ((r = opt_flag("user-rc", 1, &opts)) != -1) {
@@ -394,7 +398,7 @@ sshauthopt_parse(const char *opts, const char **errstrp)
valid_before < ret->valid_before)
ret->valid_before = valid_before;
} else if (opt_match(&opts, "environment")) {
- if (ret->nenv > INT_MAX) {
+ if (ret->nenv > SSH_AUTHOPT_ENV_MAX) {
errstr = "too many environment strings";
goto fail;
}
@@ -406,25 +410,41 @@ sshauthopt_parse(const char *opts, const char **errstrp)
errstr = "invalid environment string";
goto fail;
}
- if ((cp = strdup(opt)) == NULL)
+ if ((cp = strdup(opt)) == NULL) {
+ free(opt);
goto alloc_fail;
- cp[tmp - opt] = '\0'; /* truncate at '=' */
+ }
+ l = (size_t)(tmp - opt);
+ cp[l] = '\0'; /* truncate at '=' */
if (!valid_env_name(cp)) {
free(cp);
free(opt);
errstr = "invalid environment string";
goto fail;
}
+ /* Check for duplicates; XXX O(n*log(n)) */
+ for (i = 0; i < ret->nenv; i++) {
+ if (strncmp(ret->env[i], cp, l) == 0 &&
+ ret->env[i][l] == '=')
+ break;
+ }
free(cp);
- /* Append it. */
- oarray = ret->env;
- if ((ret->env = recallocarray(ret->env, ret->nenv,
- ret->nenv + 1, sizeof(*ret->env))) == NULL) {
- free(opt);
- ret->env = oarray; /* put it back for cleanup */
- goto alloc_fail;
+ /* First match wins */
+ if (i >= ret->nenv) {
+ /* Append it. */
+ oarray = ret->env;
+ if ((ret->env = recallocarray(ret->env,
+ ret->nenv, ret->nenv + 1,
+ sizeof(*ret->env))) == NULL) {
+ free(opt);
+ /* put it back for cleanup */
+ ret->env = oarray;
+ goto alloc_fail;
+ }
+ ret->env[ret->nenv++] = opt;
+ opt = NULL; /* transferred */
}
- ret->env[ret->nenv++] = opt;
+ free(opt);
} else if (opt_match(&opts, "permitopen")) {
if (handle_permit(&opts, 0, &ret->permitopen,
&ret->npermitopen, &errstr) != 0)
@@ -572,6 +592,7 @@ sshauthopt_merge(const struct sshauthopt *primary,
}
#define OPTFLAG_AND(x) ret->x = (primary->x == 1) && (additional->x == 1)
+#define OPTFLAG_OR(x) ret->x = (primary->x == 1) || (additional->x == 1)
/* Permissive flags are logical-AND (i.e. must be set in both) */
OPTFLAG_AND(permit_port_forwarding_flag);
OPTFLAG_AND(permit_agent_forwarding_flag);
@@ -579,6 +600,8 @@ sshauthopt_merge(const struct sshauthopt *primary,
OPTFLAG_AND(permit_pty_flag);
OPTFLAG_AND(permit_user_rc);
OPTFLAG_AND(no_require_user_presence);
+ /* Restrictive flags are logical-OR (i.e. must be set in either) */
+ OPTFLAG_OR(require_verify);
#undef OPTFLAG_AND
/* Earliest expiry time should win */
@@ -649,6 +672,7 @@ sshauthopt_copy(const struct sshauthopt *orig)
OPTSCALAR(force_tun_device);
OPTSCALAR(valid_before);
OPTSCALAR(no_require_user_presence);
+ OPTSCALAR(require_verify);
#undef OPTSCALAR
#define OPTSTRING(x) \
do { \
@@ -781,7 +805,8 @@ sshauthopt_serialise(const struct sshauthopt *opts, struct sshbuf *m,
(r = sshbuf_put_u8(m, opts->permit_user_rc)) != 0 ||
(r = sshbuf_put_u8(m, opts->restricted)) != 0 ||
(r = sshbuf_put_u8(m, opts->cert_authority)) != 0 ||
- (r = sshbuf_put_u8(m, opts->no_require_user_presence)) != 0)
+ (r = sshbuf_put_u8(m, opts->no_require_user_presence)) != 0 ||
+ (r = sshbuf_put_u8(m, opts->require_verify)) != 0)
return r;
/* Simple integer options */
@@ -802,7 +827,7 @@ sshauthopt_serialise(const struct sshauthopt *opts, struct sshbuf *m,
(r = serialise_nullable_string(m,
untrusted ? NULL : opts->required_from_host_cert)) != 0 ||
(r = serialise_nullable_string(m,
- untrusted ? NULL : opts->required_from_host_keys)) != 0)
+ untrusted ? NULL : opts->required_from_host_keys)) != 0)
return r;
/* Array options */
@@ -844,6 +869,7 @@ sshauthopt_deserialise(struct sshbuf *m, struct sshauthopt **optsp)
OPT_FLAG(restricted);
OPT_FLAG(cert_authority);
OPT_FLAG(no_require_user_presence);
+ OPT_FLAG(require_verify);
#undef OPT_FLAG
/* Simple integer options */
diff --git a/auth-options.h b/auth-options.h
index d96ffedee..6e29b727c 100644
--- a/auth-options.h
+++ b/auth-options.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-options.h,v 1.29 2019/11/25 00:54:23 djm Exp $ */
+/* $OpenBSD: auth-options.h,v 1.31 2021/07/23 03:57:20 djm Exp $ */
/*
* Copyright (c) 2018 Damien Miller <djm@mindrot.org>
@@ -23,7 +23,10 @@ struct passwd;
struct sshkey;
/* Maximum number of permitopen/permitlisten directives to accept */
-#define SSH_AUTHOPT_PERMIT_MAX 4096
+#define SSH_AUTHOPT_PERMIT_MAX 4096
+
+/* Maximum number of environment directives to accept */
+#define SSH_AUTHOPT_ENV_MAX 1024
/*
* sshauthopt represents key options parsed from authorized_keys or
@@ -71,6 +74,8 @@ struct sshauthopt {
/* Key requires user presence asserted */
int no_require_user_presence;
+ /* Key requires user verification (e.g. PIN) */
+ int require_verify;
};
struct sshauthopt *sshauthopt_new(void);
diff --git a/auth-pam.c b/auth-pam.c
index 5a3ba09b4..29034e40d 100644
--- a/auth-pam.c
+++ b/auth-pam.c
@@ -375,7 +375,11 @@ import_environments(struct sshbuf *b)
error("PAM: pam_putenv: %s",
pam_strerror(sshpam_handle, r));
}
- /* XXX leak env? */
+ /*
+ * XXX this possibly leaks env because it is not documented
+ * what pam_putenv() does with it. Does it copy it? Does it
+ * take ownweship? We don't know, so it's safest just to leak.
+ */
}
#endif
}
@@ -685,6 +689,12 @@ sshpam_init(struct ssh *ssh, Authctxt *authctxt)
const char *pam_user, *user = authctxt->user;
const char **ptr_pam_user = &pam_user;
+#if defined(PAM_SUN_CODEBASE) && defined(PAM_MAX_RESP_SIZE)
+ /* Protect buggy PAM implementations from excessively long usernames */
+ if (strlen(user) >= PAM_MAX_RESP_SIZE)
+ fatal("Username too long from %s port %d",
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
+#endif
if (sshpam_handle == NULL) {
if (ssh == NULL) {
fatal("%s: called initially with no "
@@ -717,9 +727,9 @@ sshpam_init(struct ssh *ssh, Authctxt *authctxt)
*/
sshpam_rhost = xstrdup(auth_get_canonical_hostname(ssh,
options.use_dns));
- sshpam_laddr = get_local_ipaddr(
+ sshpam_laddr = get_local_ipaddr(
ssh_packet_get_connection_in(ssh));
- xasprintf(&sshpam_conninfo, "SSH_CONNECTION=%.50s %d %.50s %d",
+ xasprintf(&sshpam_conninfo, "SSH_CONNECTION=%.50s %d %.50s %d",
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
sshpam_laddr, ssh_local_port(ssh));
}
@@ -876,6 +886,7 @@ sshpam_query(void *ctx, char **name, char **info,
case PAM_AUTH_ERR:
debug3("PAM: %s", pam_strerror(sshpam_handle, type));
if (**prompts != NULL && strlen(**prompts) != 0) {
+ free(*info);
*info = **prompts;
**prompts = NULL;
*num = 0;
@@ -1382,6 +1393,5 @@ sshpam_set_maxtries_reached(int reached)
sshpam_maxtries_reached = 1;
options.password_authentication = 0;
options.kbd_interactive_authentication = 0;
- options.challenge_response_authentication = 0;
}
#endif /* USE_PAM */
diff --git a/auth-passwd.c b/auth-passwd.c
index 24fcb67b2..347d91e25 100644
--- a/auth-passwd.c
+++ b/auth-passwd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-passwd.c,v 1.47 2018/07/09 21:26:02 markus Exp $ */
+/* $OpenBSD: auth-passwd.c,v 1.48 2020/10/18 11:32:01 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -152,14 +152,14 @@ warn_expiry(Authctxt *authctxt, auth_session_t *as)
if ((r = sshbuf_putf(loginmsg,
"Your password will expire in %lld day%s.\n",
daysleft, daysleft == 1 ? "" : "s")) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "buffer error");
}
if (actimeleft != 0 && actimeleft < acwarntime) {
daysleft = actimeleft / DAY + 1;
if ((r = sshbuf_putf(loginmsg,
"Your account will expire in %lld day%s.\n",
daysleft, daysleft == 1 ? "" : "s")) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "buffer error");
}
}
diff --git a/auth-rhosts.c b/auth-rhosts.c
index e81321b49..0bc4d424c 100644
--- a/auth-rhosts.c
+++ b/auth-rhosts.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-rhosts.c,v 1.52 2020/04/17 03:30:05 djm Exp $ */
+/* $OpenBSD: auth-rhosts.c,v 1.53 2020/10/18 11:32:01 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -223,7 +223,7 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
if (!rhosts_files[rhosts_file_index] &&
stat(_PATH_RHOSTS_EQUIV, &st) == -1 &&
stat(_PATH_SSH_HOSTS_EQUIV, &st) == -1) {
- debug3("%s: no hosts access files exist", __func__);
+ debug3_f("no hosts access files exist");
return 0;
}
@@ -232,7 +232,7 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
* shosts.equiv.
*/
if (pw->pw_uid == 0)
- debug3("%s: root user, ignoring system hosts files", __func__);
+ debug3_f("root user, ignoring system hosts files");
else {
if (check_rhosts_file(_PATH_RHOSTS_EQUIV, hostname, ipaddr,
client_user, pw->pw_name)) {
diff --git a/auth.c b/auth.c
index 7aabc8e8b..e92c5fcb9 100644
--- a/auth.c
+++ b/auth.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth.c,v 1.146 2020/01/31 22:42:45 djm Exp $ */
+/* $OpenBSD: auth.c,v 1.153 2021/07/05 00:50:25 dtucker Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -352,27 +352,29 @@ auth_log(struct ssh *ssh, int authenticated, int partial,
free(extra);
-#ifdef CUSTOM_FAILED_LOGIN
- if (authenticated == 0 && !authctxt->postponed &&
- (strcmp(method, "password") == 0 ||
- strncmp(method, "keyboard-interactive", 20) == 0 ||
- strcmp(method, "challenge-response") == 0))
- record_failed_login(ssh, authctxt->user,
- auth_get_canonical_hostname(ssh, options.use_dns), "ssh");
-# ifdef WITH_AIXAUTHENTICATE
+#if defined(CUSTOM_FAILED_LOGIN) || defined(SSH_AUDIT_EVENTS)
+ if (authenticated == 0 && !(authctxt->postponed || partial)) {
+ /* Log failed login attempt */
+# ifdef CUSTOM_FAILED_LOGIN
+ if (strcmp(method, "password") == 0 ||
+ strncmp(method, "keyboard-interactive", 20) == 0 ||
+ strcmp(method, "challenge-response") == 0)
+ record_failed_login(ssh, authctxt->user,
+ auth_get_canonical_hostname(ssh, options.use_dns), "ssh");
+# endif
+# ifdef SSH_AUDIT_EVENTS
+ audit_event(ssh, audit_classify_auth(method));
+# endif
+ }
+#endif
+#if defined(CUSTOM_FAILED_LOGIN) && defined(WITH_AIXAUTHENTICATE)
if (authenticated)
sys_auth_record_login(authctxt->user,
auth_get_canonical_hostname(ssh, options.use_dns), "ssh",
loginmsg);
-# endif
-#endif
-#ifdef SSH_AUDIT_EVENTS
- if (authenticated == 0 && !authctxt->postponed)
- audit_event(ssh, audit_classify_auth(method));
#endif
}
-
void
auth_maxtries_exceeded(struct ssh *ssh)
{
@@ -468,7 +470,7 @@ check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host,
const struct hostkey_entry *found;
hostkeys = init_hostkeys();
- load_hostkeys(hostkeys, host, sysfile);
+ load_hostkeys(hostkeys, host, sysfile, 0);
if (userfile != NULL) {
user_hostfile = tilde_expand_filename(userfile, pw->pw_uid);
if (options.strict_modes &&
@@ -482,7 +484,7 @@ check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host,
user_hostfile);
} else {
temporarily_use_uid(pw);
- load_hostkeys(hostkeys, host, user_hostfile);
+ load_hostkeys(hostkeys, host, user_hostfile, 0);
restore_uid();
}
free(user_hostfile);
@@ -492,10 +494,10 @@ check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host,
error("WARNING: revoked key for %s attempted authentication",
host);
else if (host_status == HOST_OK)
- debug("%s: key for %s found at %s:%ld", __func__,
+ debug_f("key for %s found at %s:%ld",
found->host, found->file, found->line);
else
- debug("%s: key for host %s not found", __func__, host);
+ debug_f("key for host %s not found", host);
free_hostkeys(hostkeys);
@@ -514,7 +516,7 @@ auth_openfile(const char *file, struct passwd *pw, int strict_modes,
if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) {
if (log_missing || errno != ENOENT)
debug("Could not open %s '%s': %s", file_type, file,
- strerror(errno));
+ strerror(errno));
return NULL;
}
@@ -569,11 +571,15 @@ getpwnamallow(struct ssh *ssh, const char *user)
#endif
struct passwd *pw;
struct connection_info *ci;
+ u_int i;
ci = get_connection_info(ssh, 1, options.use_dns);
ci->user = user;
parse_server_match_config(&options, &includes, ci);
log_change_level(options.log_level);
+ log_verbose_reset();
+ for (i = 0; i < options.num_log_verbose; i++)
+ log_verbose_add(options.log_verbose[i]);
process_permitopen(ssh, &options);
#if defined(_AIX) && defined(HAVE_SETAUTHDB)
@@ -608,7 +614,7 @@ getpwnamallow(struct ssh *ssh, const char *user)
if (!allowed_user(ssh, pw))
return (NULL);
#ifdef HAVE_LOGIN_CAP
- if ((lc = login_getclass(pw->pw_class)) == NULL) {
+ if ((lc = login_getpwclass(pw)) == NULL) {
debug("unable to get login class: %s", user);
return (NULL);
}
@@ -639,7 +645,7 @@ auth_key_is_revoked(struct sshkey *key)
if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
- error("%s: fingerprint key: %s", __func__, ssh_err(r));
+ error_fr(r, "fingerprint key");
goto out;
}
@@ -652,9 +658,9 @@ auth_key_is_revoked(struct sshkey *key)
sshkey_type(key), fp, options.revoked_keys_file);
goto out;
default:
- error("Error checking authentication key %s %s in "
- "revoked keys file %s: %s", sshkey_type(key), fp,
- options.revoked_keys_file, ssh_err(r));
+ error_r(r, "Error checking authentication key %s %s in "
+ "revoked keys file %s", sshkey_type(key), fp,
+ options.revoked_keys_file);
goto out;
}
@@ -680,7 +686,7 @@ auth_debug_add(const char *fmt,...)
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
if ((r = sshbuf_put_cstring(auth_debug, buf)) != 0)
- fatal("%s: sshbuf_put_cstring: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_put_cstring");
}
void
@@ -693,8 +699,7 @@ auth_debug_send(struct ssh *ssh)
return;
while (sshbuf_len(auth_debug) != 0) {
if ((r = sshbuf_get_cstring(auth_debug, &msg, NULL)) != 0)
- fatal("%s: sshbuf_get_cstring: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_get_cstring");
ssh_packet_send_debug(ssh, "%s", msg);
free(msg);
}
@@ -706,7 +711,7 @@ auth_debug_reset(void)
if (auth_debug != NULL)
sshbuf_reset(auth_debug);
else if ((auth_debug = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
}
struct passwd *
@@ -737,9 +742,7 @@ fakepw(void)
* be freed. NB. this will usually trigger a DNS query the first time it is
* called.
* This function does additional checks on the hostname to mitigate some
- * attacks on legacy rhosts-style authentication.
- * XXX is RhostsRSAAuthentication vulnerable to these?
- * XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?)
+ * attacks on based on conflation of hostnames and IP addresses.
*/
static char *
@@ -846,158 +849,6 @@ auth_get_canonical_hostname(struct ssh *ssh, int use_dns)
}
}
-/*
- * Runs command in a subprocess with a minimal environment.
- * Returns pid on success, 0 on failure.
- * The child stdout and stderr maybe captured, left attached or sent to
- * /dev/null depending on the contents of flags.
- * "tag" is prepended to log messages.
- * NB. "command" is only used for logging; the actual command executed is
- * av[0].
- */
-pid_t
-subprocess(const char *tag, struct passwd *pw, const char *command,
- int ac, char **av, FILE **child, u_int flags)
-{
- FILE *f = NULL;
- struct stat st;
- int fd, devnull, p[2], i;
- pid_t pid;
- char *cp, errmsg[512];
- u_int envsize;
- char **child_env;
-
- if (child != NULL)
- *child = NULL;
-
- debug3("%s: %s command \"%s\" running as %s (flags 0x%x)", __func__,
- tag, command, pw->pw_name, flags);
-
- /* Check consistency */
- if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 &&
- (flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0) {
- error("%s: inconsistent flags", __func__);
- return 0;
- }
- if (((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0) != (child == NULL)) {
- error("%s: inconsistent flags/output", __func__);
- return 0;
- }
-
- /*
- * If executing an explicit binary, then verify the it exists
- * and appears safe-ish to execute
- */
- if (!path_absolute(av[0])) {
- error("%s path is not absolute", tag);
- return 0;
- }
- temporarily_use_uid(pw);
- if (stat(av[0], &st) == -1) {
- error("Could not stat %s \"%s\": %s", tag,
- av[0], strerror(errno));
- restore_uid();
- return 0;
- }
- if (safe_path(av[0], &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) {
- error("Unsafe %s \"%s\": %s", tag, av[0], errmsg);
- restore_uid();
- return 0;
- }
- /* Prepare to keep the child's stdout if requested */
- if (pipe(p) == -1) {
- error("%s: pipe: %s", tag, strerror(errno));
- restore_uid();
- return 0;
- }
- restore_uid();
-
- switch ((pid = fork())) {
- case -1: /* error */
- error("%s: fork: %s", tag, strerror(errno));
- close(p[0]);
- close(p[1]);
- return 0;
- case 0: /* child */
- /* Prepare a minimal environment for the child. */
- envsize = 5;
- child_env = xcalloc(sizeof(*child_env), envsize);
- child_set_env(&child_env, &envsize, "PATH", _PATH_STDPATH);
- child_set_env(&child_env, &envsize, "USER", pw->pw_name);
- child_set_env(&child_env, &envsize, "LOGNAME", pw->pw_name);
- child_set_env(&child_env, &envsize, "HOME", pw->pw_dir);
- if ((cp = getenv("LANG")) != NULL)
- child_set_env(&child_env, &envsize, "LANG", cp);
-
- for (i = 0; i < NSIG; i++)
- ssh_signal(i, SIG_DFL);
-
- if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
- error("%s: open %s: %s", tag, _PATH_DEVNULL,
- strerror(errno));
- _exit(1);
- }
- if (dup2(devnull, STDIN_FILENO) == -1) {
- error("%s: dup2: %s", tag, strerror(errno));
- _exit(1);
- }
-
- /* Set up stdout as requested; leave stderr in place for now. */
- fd = -1;
- if ((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0)
- fd = p[1];
- else if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0)
- fd = devnull;
- if (fd != -1 && dup2(fd, STDOUT_FILENO) == -1) {
- error("%s: dup2: %s", tag, strerror(errno));
- _exit(1);
- }
- closefrom(STDERR_FILENO + 1);
-
- /* Don't use permanently_set_uid() here to avoid fatal() */
- if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1) {
- error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid,
- strerror(errno));
- _exit(1);
- }
- if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) {
- error("%s: setresuid %u: %s", tag, (u_int)pw->pw_uid,
- strerror(errno));
- _exit(1);
- }
- /* stdin is pointed to /dev/null at this point */
- if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 &&
- dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
- error("%s: dup2: %s", tag, strerror(errno));
- _exit(1);
- }
-
- execve(av[0], av, child_env);
- error("%s exec \"%s\": %s", tag, command, strerror(errno));
- _exit(127);
- default: /* parent */
- break;
- }
-
- close(p[1]);
- if ((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0)
- close(p[0]);
- else if ((f = fdopen(p[0], "r")) == NULL) {
- error("%s: fdopen: %s", tag, strerror(errno));
- close(p[0]);
- /* Don't leave zombie child */
- kill(pid, SIGTERM);
- while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
- ;
- return 0;
- }
- /* Success */
- debug3("%s: %s pid %ld", __func__, tag, (long)pid);
- if (child != NULL)
- *child = f;
- return pid;
-}
-
/* These functions link key/cert options to the auth framework */
/* Log sshauthopt options locally and (optionally) for remote transmission */
@@ -1014,21 +865,22 @@ auth_log_authopts(const char *loc, const struct sshauthopt *opts, int do_remote)
snprintf(buf, sizeof(buf), "%d", opts->force_tun_device);
/* Try to keep this alphabetically sorted */
- snprintf(msg, sizeof(msg), "key options:%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ snprintf(msg, sizeof(msg), "key options:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
opts->permit_agent_forwarding_flag ? " agent-forwarding" : "",
opts->force_command == NULL ? "" : " command",
do_env ? " environment" : "",
opts->valid_before == 0 ? "" : "expires",
+ opts->no_require_user_presence ? " no-touch-required" : "",
do_permitopen ? " permitopen" : "",
do_permitlisten ? " permitlisten" : "",
opts->permit_port_forwarding_flag ? " port-forwarding" : "",
opts->cert_principals == NULL ? "" : " principals",
opts->permit_pty_flag ? " pty" : "",
+ opts->require_verify ? " uv" : "",
opts->force_tun_device == -1 ? "" : " tun=",
opts->force_tun_device == -1 ? "" : buf,
opts->permit_user_rc ? " user-rc" : "",
- opts->permit_x11_forwarding_flag ? " x11-forwarding" : "",
- opts->no_require_user_presence ? " no-touch-required" : "");
+ opts->permit_x11_forwarding_flag ? " x11-forwarding" : "");
debug("%s: %s", loc, msg);
if (do_remote)
@@ -1076,7 +928,7 @@ auth_activate_options(struct ssh *ssh, struct sshauthopt *opts)
struct sshauthopt *old = auth_opts;
const char *emsg = NULL;
- debug("%s: setting new authentication options", __func__);
+ debug_f("setting new authentication options");
if ((auth_opts = sshauthopt_merge(old, opts, &emsg)) == NULL) {
error("Inconsistent authentication options: %s", emsg);
return -1;
@@ -1090,7 +942,7 @@ auth_restrict_session(struct ssh *ssh)
{
struct sshauthopt *restricted;
- debug("%s: restricting session", __func__);
+ debug_f("restricting session");
/* A blank sshauthopt defaults to permitting nothing */
restricted = sshauthopt_new();
@@ -1098,7 +950,7 @@ auth_restrict_session(struct ssh *ssh)
restricted->restricted = 1;
if (auth_activate_options(ssh, restricted) != 0)
- fatal("%s: failed to restrict session", __func__);
+ fatal_f("failed to restrict session");
sshauthopt_free(restricted);
}
@@ -1173,8 +1025,7 @@ auth_authorise_keyopts(struct ssh *ssh, struct passwd *pw,
case -1:
default:
/* invalid */
- error("%s: Certificate source-address invalid",
- loc);
+ error("%s: Certificate source-address invalid", loc);
/* FALLTHROUGH */
case 0:
logit("%s: Authentication tried for %.100s with valid "
diff --git a/auth.h b/auth.h
index becc672b5..43c7d3d40 100644
--- a/auth.h
+++ b/auth.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth.h,v 1.100 2019/09/06 05:23:55 djm Exp $ */
+/* $OpenBSD: auth.h,v 1.101 2020/12/22 00:12:22 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -225,12 +225,6 @@ void auth_debug_reset(void);
struct passwd *fakepw(void);
-#define SSH_SUBPROCESS_STDOUT_DISCARD (1) /* Discard stdout */
-#define SSH_SUBPROCESS_STDOUT_CAPTURE (1<<1) /* Redirect stdout */
-#define SSH_SUBPROCESS_STDERR_DISCARD (1<<2) /* Discard stderr */
-pid_t subprocess(const char *, struct passwd *,
- const char *, int, char **, FILE **, u_int flags);
-
int sys_auth_passwd(struct ssh *, const char *);
#if defined(KRB5) && !defined(HEIMDAL)
diff --git a/auth2-chall.c b/auth2-chall.c
index 3acd0a837..021df8291 100644
--- a/auth2-chall.c
+++ b/auth2-chall.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-chall.c,v 1.53 2020/02/26 13:40:09 jsg Exp $ */
+/* $OpenBSD: auth2-chall.c,v 1.54 2020/10/18 11:32:01 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2001 Per Allansson. All rights reserved.
@@ -112,15 +112,14 @@ kbdint_alloc(const char *devs)
kbdintctxt = xcalloc(1, sizeof(KbdintAuthctxt));
if (strcmp(devs, "") == 0) {
if ((b = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
for (i = 0; devices[i]; i++) {
if ((r = sshbuf_putf(b, "%s%s",
sshbuf_len(b) ? "," : "", devices[i]->name)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "buffer error");
}
if ((kbdintctxt->devices = sshbuf_dup_string(b)) == NULL)
- fatal("%s: sshbuf_dup_string failed", __func__);
+ fatal_f("sshbuf_dup_string failed");
sshbuf_free(b);
} else {
kbdintctxt->devices = xstrdup(devs);
@@ -268,15 +267,15 @@ send_userauth_info_request(struct ssh *ssh)
(r = sshpkt_put_cstring(ssh, instr)) != 0 ||
(r = sshpkt_put_cstring(ssh, "")) != 0 || /* language not used */
(r = sshpkt_put_u32(ssh, kbdintctxt->nreq)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "start packet");
for (i = 0; i < kbdintctxt->nreq; i++) {
if ((r = sshpkt_put_cstring(ssh, prompts[i])) != 0 ||
(r = sshpkt_put_u8(ssh, echo_on[i])) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble packet");
}
if ((r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send packet");
for (i = 0; i < kbdintctxt->nreq; i++)
free(prompts[i]);
@@ -299,29 +298,29 @@ input_userauth_info_response(int type, u_int32_t seq, struct ssh *ssh)
char **response = NULL;
if (authctxt == NULL)
- fatal("input_userauth_info_response: no authctxt");
+ fatal_f("no authctxt");
kbdintctxt = authctxt->kbdintctxt;
if (kbdintctxt == NULL || kbdintctxt->ctxt == NULL)
- fatal("input_userauth_info_response: no kbdintctxt");
+ fatal_f("no kbdintctxt");
if (kbdintctxt->device == NULL)
- fatal("input_userauth_info_response: no device");
+ fatal_f("no device");
authctxt->postponed = 0; /* reset */
if ((r = sshpkt_get_u32(ssh, &nresp)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse packet");
if (nresp != kbdintctxt->nreq)
- fatal("input_userauth_info_response: wrong number of replies");
+ fatal_f("wrong number of replies");
if (nresp > 100)
- fatal("input_userauth_info_response: too many replies");
+ fatal_f("too many replies");
if (nresp > 0) {
response = xcalloc(nresp, sizeof(char *));
- for (i = 0; i < nresp; i++)
- if ((r = sshpkt_get_cstring(ssh, &response[i],
- NULL)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ for (i = 0; i < nresp; i++) {
+ if ((r = sshpkt_get_cstring(ssh, &response[i], NULL)) != 0)
+ fatal_fr(r, "parse response");
+ }
}
if ((r = sshpkt_get_end(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse packet");
res = kbdintctxt->device->respond(kbdintctxt->ctxt, nresp, response);
diff --git a/auth2-gss.c b/auth2-gss.c
index 9351e0428..60e36961c 100644
--- a/auth2-gss.c
+++ b/auth2-gss.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-gss.c,v 1.29 2018/07/31 03:10:27 djm Exp $ */
+/* $OpenBSD: auth2-gss.c,v 1.32 2021/01/27 10:15:08 djm Exp $ */
/*
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
@@ -44,6 +44,7 @@
#include "misc.h"
#include "servconf.h"
#include "packet.h"
+#include "kex.h"
#include "ssh-gss.h"
#include "monitor_wrap.h"
@@ -71,7 +72,7 @@ userauth_gssapi(struct ssh *ssh)
u_char *doid = NULL;
if ((r = sshpkt_get_u32(ssh, &mechs)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse packet");
if (mechs == 0) {
debug("Mechanism negotiation is not supported");
@@ -85,7 +86,7 @@ userauth_gssapi(struct ssh *ssh)
present = 0;
if ((r = sshpkt_get_string(ssh, &doid, &len)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse oid");
if (len > 2 && doid[0] == SSH_GSS_OIDTYPE &&
doid[1] == len - 2) {
@@ -104,7 +105,7 @@ userauth_gssapi(struct ssh *ssh)
}
if (!authctxt->valid || authctxt->user == NULL) {
- debug2("%s: disabled because of invalid user", __func__);
+ debug2_f("disabled because of invalid user");
free(doid);
return (0);
}
@@ -123,7 +124,7 @@ userauth_gssapi(struct ssh *ssh)
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_GSSAPI_RESPONSE)) != 0 ||
(r = sshpkt_put_string(ssh, doid, len)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send packet");
free(doid);
@@ -152,7 +153,7 @@ input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh)
gssctxt = authctxt->methoddata;
if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse packet");
recv_tok.value = p;
recv_tok.length = len;
@@ -168,7 +169,7 @@ input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh)
(r = sshpkt_put_string(ssh, send_tok.value,
send_tok.length)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send ERRTOK packet");
}
authctxt->postponed = 0;
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
@@ -180,7 +181,7 @@ input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh)
(r = sshpkt_put_string(ssh, send_tok.value,
send_tok.length)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send TOKEN packet");
}
if (maj_status == GSS_S_COMPLETE) {
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
@@ -216,7 +217,7 @@ input_gssapi_errtok(int type, u_int32_t plen, struct ssh *ssh)
gssctxt = authctxt->methoddata;
if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse packet");
recv_tok.value = p;
recv_tok.length = len;
@@ -258,7 +259,7 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh)
*/
if ((r = sshpkt_get_end(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse packet");
authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
@@ -293,16 +294,16 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh)
gssctxt = authctxt->methoddata;
if ((r = sshpkt_get_string(ssh, &p, &len)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse packet");
if ((b = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
mic.value = p;
mic.length = len;
ssh_gssapi_buildmic(b, authctxt->user, authctxt->service,
- "gssapi-with-mic");
+ "gssapi-with-mic", ssh->kex->session_id);
if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL)
- fatal("%s: sshbuf_mutable_ptr failed", __func__);
+ fatal_f("sshbuf_mutable_ptr failed");
gssbuf.length = sshbuf_len(b);
if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
diff --git a/auth2-hostbased.c b/auth2-hostbased.c
index 5e9b7c65d..3a29126c3 100644
--- a/auth2-hostbased.c
+++ b/auth2-hostbased.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-hostbased.c,v 1.42 2019/11/25 00:51:37 djm Exp $ */
+/* $OpenBSD: auth2-hostbased.c,v 1.47 2021/07/23 03:37:52 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -35,6 +35,7 @@
#include "xmalloc.h"
#include "ssh2.h"
#include "packet.h"
+#include "kex.h"
#include "sshbuf.h"
#include "log.h"
#include "misc.h"
@@ -54,8 +55,6 @@
/* import */
extern ServerOptions options;
-extern u_char *session_id2;
-extern u_int session_id2_len;
static int
userauth_hostbased(struct ssh *ssh)
@@ -74,9 +73,9 @@ userauth_hostbased(struct ssh *ssh)
(r = sshpkt_get_cstring(ssh, &chost, NULL)) != 0 ||
(r = sshpkt_get_cstring(ssh, &cuser, NULL)) != 0 ||
(r = sshpkt_get_string(ssh, &sig, &slen)) != 0)
- fatal("%s: packet parsing: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse packet");
- debug("%s: cuser %s chost %s pkalg %s slen %zu", __func__,
+ debug_f("cuser %s chost %s pkalg %s slen %zu",
cuser, chost, pkalg, slen);
#ifdef DEBUG_PK
debug("signature:");
@@ -85,21 +84,21 @@ userauth_hostbased(struct ssh *ssh)
pktype = sshkey_type_from_name(pkalg);
if (pktype == KEY_UNSPEC) {
/* this is perfectly legal */
- logit("%s: unsupported public key algorithm: %s",
- __func__, pkalg);
+ logit_f("unsupported public key algorithm: %s",
+ pkalg);
goto done;
}
if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
- error("%s: key_from_blob: %s", __func__, ssh_err(r));
+ error_fr(r, "key_from_blob");
goto done;
}
if (key == NULL) {
- error("%s: cannot decode key: %s", __func__, pkalg);
+ error_f("cannot decode key: %s", pkalg);
goto done;
}
if (key->type != pktype) {
- error("%s: type mismatch for decoded key "
- "(received %d, expected %d)", __func__, key->type, pktype);
+ error_f("type mismatch for decoded key "
+ "(received %d, expected %d)", key->type, pktype);
goto done;
}
if (sshkey_type_plain(key->type) == KEY_RSA &&
@@ -108,28 +107,28 @@ userauth_hostbased(struct ssh *ssh)
"signature format");
goto done;
}
- if (match_pattern_list(pkalg, options.hostbased_key_types, 0) != 1) {
- logit("%s: key type %s not in HostbasedAcceptedKeyTypes",
- __func__, sshkey_type(key));
+ if (match_pattern_list(pkalg, options.hostbased_accepted_algos, 0) != 1) {
+ logit_f("key type %s not in HostbasedAcceptedAlgorithms",
+ sshkey_type(key));
goto done;
}
if ((r = sshkey_check_cert_sigtype(key,
options.ca_sign_algorithms)) != 0) {
- logit("%s: certificate signature algorithm %s: %s", __func__,
+ logit_fr(r, "certificate signature algorithm %s",
(key->cert == NULL || key->cert->signature_type == NULL) ?
- "(null)" : key->cert->signature_type, ssh_err(r));
+ "(null)" : key->cert->signature_type);
goto done;
}
if (!authctxt->valid || authctxt->user == NULL) {
- debug2("%s: disabled because of invalid user", __func__);
+ debug2_f("disabled because of invalid user");
goto done;
}
if ((b = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
/* reconstruct packet */
- if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 ||
+ if ((r = sshbuf_put_stringb(b, ssh->kex->session_id)) != 0 ||
(r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->user)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->service)) != 0 ||
@@ -138,7 +137,7 @@ userauth_hostbased(struct ssh *ssh)
(r = sshbuf_put_string(b, pkblob, blen)) != 0 ||
(r = sshbuf_put_cstring(b, chost)) != 0 ||
(r = sshbuf_put_cstring(b, cuser)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reconstruct packet");
#ifdef DEBUG_PK
sshbuf_dump(b, stderr);
#endif
@@ -157,7 +156,7 @@ userauth_hostbased(struct ssh *ssh)
auth2_record_key(authctxt, authenticated, key);
sshbuf_free(b);
done:
- debug2("%s: authenticated %d", __func__, authenticated);
+ debug2_f("authenticated %d", authenticated);
sshkey_free(key);
free(pkalg);
free(pkblob);
@@ -183,7 +182,7 @@ hostbased_key_allowed(struct ssh *ssh, struct passwd *pw,
resolvedname = auth_get_canonical_hostname(ssh, options.use_dns);
ipaddr = ssh_remote_ipaddr(ssh);
- debug2("%s: chost %s resolvedname %s ipaddr %s", __func__,
+ debug2_f("chost %s resolvedname %s ipaddr %s",
chost, resolvedname, ipaddr);
if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
@@ -193,9 +192,8 @@ hostbased_key_allowed(struct ssh *ssh, struct passwd *pw,
if (options.hostbased_uses_name_from_packet_only) {
if (auth_rhosts2(pw, cuser, chost, chost) == 0) {
- debug2("%s: auth_rhosts2 refused "
- "user \"%.100s\" host \"%.100s\" (from packet)",
- __func__, cuser, chost);
+ debug2_f("auth_rhosts2 refused user \"%.100s\" "
+ "host \"%.100s\" (from packet)", cuser, chost);
return 0;
}
lookup = chost;
@@ -205,17 +203,17 @@ hostbased_key_allowed(struct ssh *ssh, struct passwd *pw,
"client sends %s, but we resolve %s to %s",
chost, ipaddr, resolvedname);
if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0) {
- debug2("%s: auth_rhosts2 refused "
+ debug2_f("auth_rhosts2 refused "
"user \"%.100s\" host \"%.100s\" addr \"%.100s\"",
- __func__, cuser, resolvedname, ipaddr);
+ cuser, resolvedname, ipaddr);
return 0;
}
lookup = resolvedname;
}
- debug2("%s: access allowed by auth_rhosts2", __func__);
+ debug2_f("access allowed by auth_rhosts2");
if (sshkey_is_cert(key) &&
- sshkey_cert_check_authority(key, 1, 0, lookup, &reason)) {
+ sshkey_cert_check_authority_now(key, 1, 0, 0, lookup, &reason)) {
error("%s", reason);
auth_debug_add("%s", reason);
return 0;
@@ -237,7 +235,7 @@ hostbased_key_allowed(struct ssh *ssh, struct passwd *pw,
if (sshkey_is_cert(key)) {
if ((fp = sshkey_fingerprint(key->cert->signature_key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
- fatal("%s: sshkey_fingerprint fail", __func__);
+ fatal_f("sshkey_fingerprint fail");
verbose("Accepted certificate ID \"%s\" signed by "
"%s CA %s from %s@%s", key->cert->key_id,
sshkey_type(key->cert->signature_key), fp,
@@ -245,7 +243,7 @@ hostbased_key_allowed(struct ssh *ssh, struct passwd *pw,
} else {
if ((fp = sshkey_fingerprint(key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
- fatal("%s: sshkey_fingerprint fail", __func__);
+ fatal_f("sshkey_fingerprint fail");
verbose("Accepted %s public key %s from %s@%s",
sshkey_type(key), fp, cuser, lookup);
}
diff --git a/auth2-kbdint.c b/auth2-kbdint.c
index e23d2edd2..037139d44 100644
--- a/auth2-kbdint.c
+++ b/auth2-kbdint.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-kbdint.c,v 1.11 2019/11/13 04:47:52 deraadt Exp $ */
+/* $OpenBSD: auth2-kbdint.c,v 1.13 2021/07/02 05:11:20 dtucker Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -52,11 +52,11 @@ userauth_kbdint(struct ssh *ssh)
if ((r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0 ||
(r = sshpkt_get_cstring(ssh, &devs, NULL)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse packet");
debug("keyboard-interactive devs %s", devs);
- if (options.challenge_response_authentication)
+ if (options.kbd_interactive_authentication)
authenticated = auth2_challenge(ssh, devs);
free(devs);
diff --git a/auth2-none.c b/auth2-none.c
index f457c3782..a69fb2a74 100644
--- a/auth2-none.c
+++ b/auth2-none.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-none.c,v 1.22 2018/07/09 21:35:50 markus Exp $ */
+/* $OpenBSD: auth2-none.c,v 1.23 2020/10/18 11:32:01 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -65,7 +65,7 @@ userauth_none(struct ssh *ssh)
none_enabled = 0;
if ((r = sshpkt_get_end(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse packet");
/* no password authentication in Android. */
#if !defined(ANDROID)
diff --git a/auth2-passwd.c b/auth2-passwd.c
index 2d0b2af22..8e7fa73c6 100644
--- a/auth2-passwd.c
+++ b/auth2-passwd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-passwd.c,v 1.18 2020/02/26 13:40:09 jsg Exp $ */
+/* $OpenBSD: auth2-passwd.c,v 1.19 2020/10/18 11:32:01 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -60,7 +60,7 @@ userauth_passwd(struct ssh *ssh)
(r = sshpkt_get_cstring(ssh, &password, &len)) != 0 ||
(change && (r = sshpkt_get_cstring(ssh, NULL, NULL)) != 0) ||
(r = sshpkt_get_end(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse packet");
if (change)
logit("password change not supported");
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index 815ea0f25..9e32259a5 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-pubkey.c,v 1.99 2020/02/06 22:30:54 naddy Exp $ */
+/* $OpenBSD: auth2-pubkey.c,v 1.109 2021/07/23 03:37:52 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -47,6 +47,7 @@
#include "ssh.h"
#include "ssh2.h"
#include "packet.h"
+#include "kex.h"
#include "sshbuf.h"
#include "log.h"
#include "misc.h"
@@ -72,8 +73,6 @@
/* import */
extern ServerOptions options;
-extern u_char *session_id2;
-extern u_int session_id2_len;
static char *
format_key(const struct sshkey *key)
@@ -97,24 +96,24 @@ userauth_pubkey(struct ssh *ssh)
u_char *pkblob = NULL, *sig = NULL, have_sig;
size_t blen, slen;
int r, pktype;
- int req_presence = 0, authenticated = 0;
+ int req_presence = 0, req_verify = 0, authenticated = 0;
struct sshauthopt *authopts = NULL;
struct sshkey_sig_details *sig_details = NULL;
if ((r = sshpkt_get_u8(ssh, &have_sig)) != 0 ||
(r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 ||
(r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0)
- fatal("%s: parse request failed: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse packet");
if (log_level_get() >= SYSLOG_LEVEL_DEBUG2) {
char *keystring;
struct sshbuf *pkbuf;
if ((pkbuf = sshbuf_from(pkblob, blen)) == NULL)
- fatal("%s: sshbuf_from failed", __func__);
+ fatal_f("sshbuf_from failed");
if ((keystring = sshbuf_dtob64_string(pkbuf, 0)) == NULL)
- fatal("%s: sshbuf_dtob64 failed", __func__);
- debug2("%s: %s user %s %s public key %s %s", __func__,
+ fatal_f("sshbuf_dtob64 failed");
+ debug2_f("%s user %s %s public key %s %s",
authctxt->valid ? "valid" : "invalid", authctxt->user,
have_sig ? "attempting" : "querying", pkalg, keystring);
sshbuf_free(pkbuf);
@@ -124,21 +123,20 @@ userauth_pubkey(struct ssh *ssh)
pktype = sshkey_type_from_name(pkalg);
if (pktype == KEY_UNSPEC) {
/* this is perfectly legal */
- verbose("%s: unsupported public key algorithm: %s",
- __func__, pkalg);
+ verbose_f("unsupported public key algorithm: %s", pkalg);
goto done;
}
if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
- error("%s: could not parse key: %s", __func__, ssh_err(r));
+ error_fr(r, "parse key");
goto done;
}
if (key == NULL) {
- error("%s: cannot decode key: %s", __func__, pkalg);
+ error_f("cannot decode key: %s", pkalg);
goto done;
}
if (key->type != pktype) {
- error("%s: type mismatch for decoded key "
- "(received %d, expected %d)", __func__, key->type, pktype);
+ error_f("type mismatch for decoded key "
+ "(received %d, expected %d)", key->type, pktype);
goto done;
}
if (sshkey_type_plain(key->type) == KEY_RSA &&
@@ -151,16 +149,16 @@ userauth_pubkey(struct ssh *ssh)
logit("refusing previously-used %s key", sshkey_type(key));
goto done;
}
- if (match_pattern_list(pkalg, options.pubkey_key_types, 0) != 1) {
- logit("%s: key type %s not in PubkeyAcceptedKeyTypes",
- __func__, sshkey_ssh_name(key));
+ if (match_pattern_list(pkalg, options.pubkey_accepted_algos, 0) != 1) {
+ logit_f("key type %s not in PubkeyAcceptedAlgorithms",
+ sshkey_ssh_name(key));
goto done;
}
if ((r = sshkey_check_cert_sigtype(key,
options.ca_sign_algorithms)) != 0) {
- logit("%s: certificate signature algorithm %s: %s", __func__,
+ logit_fr(r, "certificate signature algorithm %s",
(key->cert == NULL || key->cert->signature_type == NULL) ?
- "(null)" : key->cert->signature_type, ssh_err(r));
+ "(null)" : key->cert->signature_type);
goto done;
}
key_s = format_key(key);
@@ -168,29 +166,23 @@ userauth_pubkey(struct ssh *ssh)
ca_s = format_key(key->cert->signature_key);
if (have_sig) {
- debug3("%s: have %s signature for %s%s%s",
- __func__, pkalg, key_s,
- ca_s == NULL ? "" : " CA ",
- ca_s == NULL ? "" : ca_s);
+ debug3_f("have %s signature for %s%s%s", pkalg, key_s,
+ ca_s == NULL ? "" : " CA ", ca_s == NULL ? "" : ca_s);
if ((r = sshpkt_get_string(ssh, &sig, &slen)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse signature packet");
if ((b = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if (ssh->compat & SSH_OLD_SESSIONID) {
- if ((r = sshbuf_put(b, session_id2,
- session_id2_len)) != 0)
- fatal("%s: sshbuf_put session id: %s",
- __func__, ssh_err(r));
+ if ((r = sshbuf_putb(b, ssh->kex->session_id)) != 0)
+ fatal_fr(r, "put old session id");
} else {
- if ((r = sshbuf_put_string(b, session_id2,
- session_id2_len)) != 0)
- fatal("%s: sshbuf_put_string session id: %s",
- __func__, ssh_err(r));
+ if ((r = sshbuf_put_stringb(b,
+ ssh->kex->session_id)) != 0)
+ fatal_fr(r, "put session id");
}
if (!authctxt->valid || authctxt->user == NULL) {
- debug2("%s: disabled because of invalid user",
- __func__);
+ debug2_f("disabled because of invalid user");
goto done;
}
/* reconstruct packet */
@@ -204,8 +196,7 @@ userauth_pubkey(struct ssh *ssh)
(r = sshbuf_put_u8(b, have_sig)) != 0 ||
(r = sshbuf_put_cstring(b, pkalg)) != 0 ||
(r = sshbuf_put_string(b, pkblob, blen)) != 0)
- fatal("%s: build packet failed: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "reconstruct packet");
#ifdef DEBUG_PK
sshbuf_dump(b, stderr);
#endif
@@ -221,9 +212,8 @@ userauth_pubkey(struct ssh *ssh)
if (authenticated == 1 && sig_details != NULL) {
auth2_record_info(authctxt, "signature count = %u",
sig_details->sk_counter);
- debug("%s: sk_counter = %u, sk_flags = 0x%02x",
- __func__, sig_details->sk_counter,
- sig_details->sk_flags);
+ debug_f("sk_counter = %u, sk_flags = 0x%02x",
+ sig_details->sk_counter, sig_details->sk_flags);
req_presence = (options.pubkey_auth_options &
PUBKEYAUTH_TOUCH_REQUIRED) ||
!authopts->no_require_user_presence;
@@ -239,20 +229,31 @@ userauth_pubkey(struct ssh *ssh)
authenticated = 0;
goto done;
}
+ req_verify = (options.pubkey_auth_options &
+ PUBKEYAUTH_VERIFY_REQUIRED) ||
+ authopts->require_verify;
+ if (req_verify && (sig_details->sk_flags &
+ SSH_SK_USER_VERIFICATION_REQD) == 0) {
+ error("public key %s signature for %s%s from "
+ "%.128s port %d rejected: user "
+ "verification requirement not met ", key_s,
+ authctxt->valid ? "" : "invalid user ",
+ authctxt->user, ssh_remote_ipaddr(ssh),
+ ssh_remote_port(ssh));
+ authenticated = 0;
+ goto done;
+ }
}
auth2_record_key(authctxt, authenticated, key);
} else {
- debug("%s: test pkalg %s pkblob %s%s%s",
- __func__, pkalg, key_s,
- ca_s == NULL ? "" : " CA ",
- ca_s == NULL ? "" : ca_s);
+ debug_f("test pkalg %s pkblob %s%s%s", pkalg, key_s,
+ ca_s == NULL ? "" : " CA ", ca_s == NULL ? "" : ca_s);
if ((r = sshpkt_get_end(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse packet");
if (!authctxt->valid || authctxt->user == NULL) {
- debug2("%s: disabled because of invalid user",
- __func__);
+ debug2_f("disabled because of invalid user");
goto done;
}
/* XXX fake reply and always send PK_OK ? */
@@ -270,16 +271,16 @@ userauth_pubkey(struct ssh *ssh)
(r = sshpkt_put_string(ssh, pkblob, blen)) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send packet");
authctxt->postponed = 1;
}
}
done:
if (authenticated == 1 && auth_activate_options(ssh, authopts) != 0) {
- debug("%s: key options inconsistent with existing", __func__);
+ debug_f("key options inconsistent with existing");
authenticated = 0;
}
- debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg);
+ debug2_f("authenticated %d pkalg %s", authenticated, pkalg);
sshbuf_free(b);
sshauthopt_free(authopts);
@@ -474,7 +475,8 @@ match_principals_command(struct ssh *ssh, struct passwd *user_pw,
}
/* Turn the command into an argument vector */
- if (argv_split(options.authorized_principals_command, &ac, &av) != 0) {
+ if (argv_split(options.authorized_principals_command,
+ &ac, &av, 0) != 0) {
error("AuthorizedPrincipalsCommand \"%s\" contains "
"invalid quotes", options.authorized_principals_command);
goto out;
@@ -486,20 +488,20 @@ match_principals_command(struct ssh *ssh, struct passwd *user_pw,
}
if ((ca_fp = sshkey_fingerprint(cert->signature_key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
- error("%s: sshkey_fingerprint failed", __func__);
+ error_f("sshkey_fingerprint failed");
goto out;
}
if ((key_fp = sshkey_fingerprint(key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
- error("%s: sshkey_fingerprint failed", __func__);
+ error_f("sshkey_fingerprint failed");
goto out;
}
if ((r = sshkey_to_base64(cert->signature_key, &catext)) != 0) {
- error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r));
+ error_fr(r, "sshkey_to_base64 failed");
goto out;
}
if ((r = sshkey_to_base64(key, &keytext)) != 0) {
- error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r));
+ error_fr(r, "sshkey_to_base64 failed");
goto out;
}
snprintf(serial_s, sizeof(serial_s), "%llu",
@@ -521,16 +523,17 @@ match_principals_command(struct ssh *ssh, struct passwd *user_pw,
"s", serial_s,
(char *)NULL);
if (tmp == NULL)
- fatal("%s: percent_expand failed", __func__);
+ fatal_f("percent_expand failed");
free(av[i]);
av[i] = tmp;
}
/* Prepare a printable command for logs, etc. */
command = argv_assemble(ac, av);
- if ((pid = subprocess("AuthorizedPrincipalsCommand", runas_pw, command,
+ if ((pid = subprocess("AuthorizedPrincipalsCommand", command,
ac, av, &f,
- SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0)
+ SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD,
+ runas_pw, temporarily_use_uid, restore_uid)) == 0)
goto out;
uid_swapped = 1;
@@ -584,7 +587,7 @@ check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
*authoptsp = NULL;
if ((found = sshkey_new(want_keytype)) == NULL) {
- debug3("%s: keytype %d failed", __func__, want_keytype);
+ debug3_f("keytype %d failed", want_keytype);
goto out;
}
@@ -626,7 +629,7 @@ check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
/* We have a candidate key, perform authorisation checks */
if ((fp = sshkey_fingerprint(found,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
- fatal("%s: fingerprint failed", __func__);
+ fatal_f("fingerprint failed");
debug("%s: matching %s found: %s %s", loc,
sshkey_is_cert(key) ? "CA" : "key", sshkey_type(found), fp);
@@ -671,8 +674,9 @@ check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
reason = "Certificate does not contain an authorized principal";
goto fail_reason;
}
- if (sshkey_cert_check_authority(key, 0, 0,
- keyopts->cert_principals == NULL ? pw->pw_name : NULL, &reason) != 0)
+ if (sshkey_cert_check_authority_now(key, 0, 0, 0,
+ keyopts->cert_principals == NULL ? pw->pw_name : NULL,
+ &reason) != 0)
goto fail_reason;
verbose("Accepted certificate ID \"%s\" (serial %llu) "
@@ -683,7 +687,7 @@ check_authkey_line(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
success:
if (finalopts == NULL)
- fatal("%s: internal error: missing options", __func__);
+ fatal_f("internal error: missing options");
if (authoptsp != NULL) {
*authoptsp = finalopts;
finalopts = NULL;
@@ -762,9 +766,9 @@ user_cert_trusted_ca(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
if ((r = sshkey_in_file(key->cert->signature_key,
options.trusted_user_ca_keys, 1, 0)) != 0) {
- debug2("%s: CA %s %s is not listed in %s: %s", __func__,
+ debug2_fr(r, "CA %s %s is not listed in %s",
sshkey_type(key->cert->signature_key), ca_fp,
- options.trusted_user_ca_keys, ssh_err(r));
+ options.trusted_user_ca_keys);
goto out;
}
/*
@@ -783,14 +787,14 @@ user_cert_trusted_ca(struct ssh *ssh, struct passwd *pw, struct sshkey *key,
found_principal = 1;
/* If principals file or command is specified, then require a match */
use_authorized_principals = principals_file != NULL ||
- options.authorized_principals_command != NULL;
+ options.authorized_principals_command != NULL;
if (!found_principal && use_authorized_principals) {
reason = "Certificate does not contain an authorized principal";
goto fail_reason;
}
if (use_authorized_principals && principals_opts == NULL)
- fatal("%s: internal error: missing principals_opts", __func__);
- if (sshkey_cert_check_authority(key, 0, 1,
+ fatal_f("internal error: missing principals_opts");
+ if (sshkey_cert_check_authority_now(key, 0, 1, 0,
use_authorized_principals ? NULL : pw->pw_name, &reason) != 0)
goto fail_reason;
@@ -914,23 +918,23 @@ user_key_command_allowed2(struct ssh *ssh, struct passwd *user_pw,
/* Prepare AuthorizedKeysCommand */
if ((key_fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL) {
- error("%s: sshkey_fingerprint failed", __func__);
+ error_f("sshkey_fingerprint failed");
goto out;
}
if ((r = sshkey_to_base64(key, &keytext)) != 0) {
- error("%s: sshkey_to_base64 failed: %s", __func__, ssh_err(r));
+ error_fr(r, "sshkey_to_base64 failed");
goto out;
}
/* Turn the command into an argument vector */
- if (argv_split(options.authorized_keys_command, &ac, &av) != 0) {
+ if (argv_split(options.authorized_keys_command, &ac, &av, 0) != 0) {
error("AuthorizedKeysCommand \"%s\" contains invalid quotes",
- command);
+ options.authorized_keys_command);
goto out;
}
if (ac == 0) {
error("AuthorizedKeysCommand \"%s\" yielded no arguments",
- command);
+ options.authorized_keys_command);
goto out;
}
snprintf(uidstr, sizeof(uidstr), "%llu",
@@ -945,7 +949,7 @@ user_key_command_allowed2(struct ssh *ssh, struct passwd *user_pw,
"k", keytext,
(char *)NULL);
if (tmp == NULL)
- fatal("%s: percent_expand failed", __func__);
+ fatal_f("percent_expand failed");
free(av[i]);
av[i] = tmp;
}
@@ -966,9 +970,10 @@ user_key_command_allowed2(struct ssh *ssh, struct passwd *user_pw,
xasprintf(&command, "%s %s", av[0], av[1]);
}
- if ((pid = subprocess("AuthorizedKeysCommand", runas_pw, command,
+ if ((pid = subprocess("AuthorizedKeysCommand", command,
ac, av, &f,
- SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD)) == 0)
+ SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD,
+ runas_pw, temporarily_use_uid, restore_uid)) == 0)
goto out;
uid_swapped = 1;
diff --git a/auth2.c b/auth2.c
index 91aaf34a6..84d0ed16e 100644
--- a/auth2.c
+++ b/auth2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2.c,v 1.158 2020/03/06 18:16:21 markus Exp $ */
+/* $OpenBSD: auth2.c,v 1.161 2021/04/03 06:18:40 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@@ -61,8 +61,6 @@
/* import */
extern ServerOptions options;
-extern u_char *session_id2;
-extern u_int session_id2_len;
extern struct sshbuf *loginmsg;
/* methods */
@@ -145,7 +143,7 @@ userauth_send_banner(struct ssh *ssh, const char *msg)
(r = sshpkt_put_cstring(ssh, msg)) != 0 ||
(r = sshpkt_put_cstring(ssh, "")) != 0 || /* language, unused */
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send packet");
debug("%s: sent", __func__);
}
@@ -230,13 +228,13 @@ user_specific_delay(const char *user)
double delay;
(void)snprintf(b, sizeof b, "%llu%s",
- (unsigned long long)options.timing_secret, user);
+ (unsigned long long)options.timing_secret, user);
if (ssh_digest_memory(SSH_DIGEST_SHA512, b, strlen(b), hash, len) != 0)
- fatal("%s: ssh_digest_memory", __func__);
+ fatal_f("ssh_digest_memory");
/* 0-4.2 ms of delay */
delay = (double)PEEK_U32(hash) / 1000 / 1000 / 1000 / 1000;
freezero(hash, len);
- debug3("%s: user specific delay %0.3lfms", __func__, delay/1000);
+ debug3_f("user specific delay %0.3lfms", delay/1000);
return MIN_FAIL_DELAY_SECONDS + delay;
}
@@ -252,8 +250,8 @@ ensure_minimum_time_since(double start, double seconds)
ts.tv_sec = remain;
ts.tv_nsec = (remain - ts.tv_sec) * 1000000000;
- debug3("%s: elapsed %0.3lfms, delaying %0.3lfms (requested %0.3lfms)",
- __func__, elapsed*1000, remain*1000, req*1000);
+ debug3_f("elapsed %0.3lfms, delaying %0.3lfms (requested %0.3lfms)",
+ elapsed*1000, remain*1000, req*1000);
nanosleep(&ts, NULL);
}
@@ -286,8 +284,7 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
authctxt->user = xstrdup(user);
if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
authctxt->valid = 1;
- debug2("%s: setting up authctxt for %s",
- __func__, user);
+ debug2_f("setting up authctxt for %s", user);
} else {
/* Invalid user, fake password information */
authctxt->pw = fakepw();
@@ -390,20 +387,20 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method,
#ifdef USE_PAM
if (options.use_pam && authenticated) {
- int r;
-
- if (!PRIVSEP(do_pam_account())) {
- /* if PAM returned a message, send it to the user */
- if (sshbuf_len(loginmsg) > 0) {
- if ((r = sshbuf_put(loginmsg, "\0", 1)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
- userauth_send_banner(ssh, sshbuf_ptr(loginmsg));
- if ((r = ssh_packet_write_wait(ssh)) != 0) {
- sshpkt_fatal(ssh, r,
- "%s: send PAM banner", __func__);
- }
+ int r, success = PRIVSEP(do_pam_account());
+
+ /* If PAM returned a message, send it to the user. */
+ if (sshbuf_len(loginmsg) > 0) {
+ if ((r = sshbuf_put(loginmsg, "\0", 1)) != 0)
+ fatal("%s: buffer error: %s",
+ __func__, ssh_err(r));
+ userauth_send_banner(ssh, sshbuf_ptr(loginmsg));
+ if ((r = ssh_packet_write_wait(ssh)) != 0) {
+ sshpkt_fatal(ssh, r,
+ "%s: send PAM banner", __func__);
}
+ }
+ if (!success) {
fatal("Access denied for user %s by PAM account "
"configuration", authctxt->user);
}
@@ -417,7 +414,7 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method,
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_SUCCESS)) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send success packet");
/* now we can break out */
authctxt->success = 1;
ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user);
@@ -433,14 +430,14 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method,
auth_maxtries_exceeded(ssh);
}
methods = authmethods_get(authctxt);
- debug3("%s: failure partial=%d next methods=\"%s\"", __func__,
+ debug3_f("failure partial=%d next methods=\"%s\"",
partial, methods);
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_FAILURE)) != 0 ||
(r = sshpkt_put_cstring(ssh, methods)) != 0 ||
(r = sshpkt_put_u8(ssh, partial)) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send failure packet");
free(methods);
}
}
@@ -478,7 +475,7 @@ authmethods_get(Authctxt *authctxt)
int i, r;
if ((b = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
for (i = 0; authmethods[i] != NULL; i++) {
if (strcmp(authmethods[i]->name, "none") == 0)
continue;
@@ -490,10 +487,10 @@ authmethods_get(Authctxt *authctxt)
continue;
if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) ? "," : "",
authmethods[i]->name)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "buffer error");
}
if ((list = sshbuf_dup_string(b)) == NULL)
- fatal("%s: sshbuf_dup_string failed", __func__);
+ fatal_f("sshbuf_dup_string failed");
sshbuf_free(b);
return list;
}
@@ -585,7 +582,7 @@ auth2_setup_methods_lists(Authctxt *authctxt)
if (options.num_auth_methods == 0)
return 0;
- debug3("%s: checking methods", __func__);
+ debug3_f("checking methods");
authctxt->auth_methods = xcalloc(options.num_auth_methods,
sizeof(*authctxt->auth_methods));
authctxt->num_auth_methods = 0;
@@ -673,7 +670,7 @@ auth2_update_methods_lists(Authctxt *authctxt, const char *method,
{
u_int i, found = 0;
- debug3("%s: updating methods list after \"%s\"", __func__, method);
+ debug3_f("updating methods list after \"%s\"", method);
for (i = 0; i < authctxt->num_auth_methods; i++) {
if (!remove_method(&(authctxt->auth_methods[i]), method,
submethod))
@@ -688,7 +685,7 @@ auth2_update_methods_lists(Authctxt *authctxt, const char *method,
}
/* This should not happen, but would be bad if it did */
if (!found)
- fatal("%s: method not in AuthenticationMethods", __func__);
+ fatal_f("method not in AuthenticationMethods");
return 0;
}
@@ -706,7 +703,7 @@ void
auth2_record_info(Authctxt *authctxt, const char *fmt, ...)
{
va_list ap;
- int i;
+ int i;
free(authctxt->auth_method_info);
authctxt->auth_method_info = NULL;
@@ -716,7 +713,7 @@ auth2_record_info(Authctxt *authctxt, const char *fmt, ...)
va_end(ap);
if (i == -1)
- fatal("%s: vasprintf failed", __func__);
+ fatal_f("vasprintf failed");
}
/*
@@ -732,7 +729,7 @@ auth2_record_key(Authctxt *authctxt, int authenticated,
int r;
if ((r = sshkey_from_private(key, &dup)) != 0)
- fatal("%s: copy key: %s", __func__, ssh_err(r));
+ fatal_fr(r, "copy key");
sshkey_free(authctxt->auth_method_key);
authctxt->auth_method_key = dup;
@@ -741,11 +738,11 @@ auth2_record_key(Authctxt *authctxt, int authenticated,
/* If authenticated, make sure we don't accept this key again */
if ((r = sshkey_from_private(key, &dup)) != 0)
- fatal("%s: copy key: %s", __func__, ssh_err(r));
+ fatal_fr(r, "copy key");
if (authctxt->nprev_keys >= INT_MAX ||
(tmp = recallocarray(authctxt->prev_keys, authctxt->nprev_keys,
authctxt->nprev_keys + 1, sizeof(*authctxt->prev_keys))) == NULL)
- fatal("%s: reallocarray failed", __func__);
+ fatal_f("reallocarray failed");
authctxt->prev_keys = tmp;
authctxt->prev_keys[authctxt->nprev_keys] = dup;
authctxt->nprev_keys++;
@@ -763,7 +760,7 @@ auth2_key_already_used(Authctxt *authctxt, const struct sshkey *key)
if (sshkey_equal_public(key, authctxt->prev_keys[i])) {
fp = sshkey_fingerprint(authctxt->prev_keys[i],
options.fingerprint_hash, SSH_FP_DEFAULT);
- debug3("%s: key already used: %s %s", __func__,
+ debug3_f("key already used: %s %s",
sshkey_type(authctxt->prev_keys[i]),
fp == NULL ? "UNKNOWN" : fp);
free(fp);
@@ -785,35 +782,34 @@ auth2_update_session_info(Authctxt *authctxt, const char *method,
if (authctxt->session_info == NULL) {
if ((authctxt->session_info = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
}
/* Append method[/submethod] */
if ((r = sshbuf_putf(authctxt->session_info, "%s%s%s",
method, submethod == NULL ? "" : "/",
submethod == NULL ? "" : submethod)) != 0)
- fatal("%s: append method: %s", __func__, ssh_err(r));
+ fatal_fr(r, "append method");
/* Append key if present */
if (authctxt->auth_method_key != NULL) {
if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 ||
(r = sshkey_format_text(authctxt->auth_method_key,
authctxt->session_info)) != 0)
- fatal("%s: append key: %s", __func__, ssh_err(r));
+ fatal_fr(r, "append key");
}
if (authctxt->auth_method_info != NULL) {
/* Ensure no ambiguity here */
if (strchr(authctxt->auth_method_info, '\n') != NULL)
- fatal("%s: auth_method_info contains \\n", __func__);
+ fatal_f("auth_method_info contains \\n");
if ((r = sshbuf_put_u8(authctxt->session_info, ' ')) != 0 ||
(r = sshbuf_putf(authctxt->session_info, "%s",
authctxt->auth_method_info)) != 0) {
- fatal("%s: append method info: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "append method info");
}
}
if ((r = sshbuf_put_u8(authctxt->session_info, '\n')) != 0)
- fatal("%s: append: %s", __func__, ssh_err(r));
+ fatal_fr(r, "append");
}
diff --git a/authfd.c b/authfd.c
index 4b647a628..9f092f7cf 100644
--- a/authfd.c
+++ b/authfd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfd.c,v 1.123 2020/03/06 18:24:39 markus Exp $ */
+/* $OpenBSD: authfd.c,v 1.127 2021/01/26 00:46:17 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -62,7 +62,7 @@
#include "ssherr.h"
#define MAX_AGENT_IDENTITIES 2048 /* Max keys in agent reply */
-#define MAX_AGENT_REPLY_LEN (256 * 1024) /* Max bytes in agent reply */
+#define MAX_AGENT_REPLY_LEN (256 * 1024) /* Max bytes in agent reply */
/* macro to check for "agent failure" message */
#define agent_failed(x) \
@@ -177,6 +177,27 @@ ssh_request_reply(int sock, struct sshbuf *request, struct sshbuf *reply)
return 0;
}
+/* Communicate with agent: sent request, read and decode status reply */
+static int
+ssh_request_reply_decode(int sock, struct sshbuf *request)
+{
+ struct sshbuf *reply;
+ int r;
+ u_char type;
+
+ if ((reply = sshbuf_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ if ((r = ssh_request_reply(sock, request, reply)) != 0 ||
+ (r = sshbuf_get_u8(reply, &type)) != 0 ||
+ (r = decode_reply(type)) != 0)
+ goto out;
+ /* success */
+ r = 0;
+ out:
+ sshbuf_free(reply);
+ return r;
+}
+
/*
* Closes the agent socket if it should be closed (depends on how it was
* obtained). The argument must have been returned by
@@ -200,13 +221,11 @@ ssh_lock_agent(int sock, int lock, const char *password)
if ((msg = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_put_u8(msg, type)) != 0 ||
- (r = sshbuf_put_cstring(msg, password)) != 0)
- goto out;
- if ((r = ssh_request_reply(sock, msg, msg)) != 0)
+ (r = sshbuf_put_cstring(msg, password)) != 0 ||
+ (r = ssh_request_reply_decode(sock, msg)) != 0)
goto out;
- if ((r = sshbuf_get_u8(msg, &type)) != 0)
- goto out;
- r = decode_reply(type);
+ /* success */
+ r = 0;
out:
sshbuf_free(msg);
return r;
@@ -336,7 +355,7 @@ ssh_free_identitylist(struct ssh_identitylist *idl)
* Returns 0 if found, or a negative SSH_ERR_* error code on failure.
*/
int
-ssh_agent_has_key(int sock, struct sshkey *key)
+ssh_agent_has_key(int sock, const struct sshkey *key)
{
int r, ret = SSH_ERR_KEY_NOT_FOUND;
size_t i;
@@ -507,7 +526,7 @@ ssh_add_identity_constrained(int sock, struct sshkey *key,
SSH2_AGENTC_ADD_IDENTITY;
if ((r = sshbuf_put_u8(msg, type)) != 0 ||
(r = sshkey_private_serialize_maxsign(key, msg, maxsign,
- NULL)) != 0 ||
+ 0)) != 0 ||
(r = sshbuf_put_cstring(msg, comment)) != 0)
goto out;
break;
@@ -519,11 +538,10 @@ ssh_add_identity_constrained(int sock, struct sshkey *key,
(r = encode_constraints(msg, life, confirm, maxsign,
provider)) != 0)
goto out;
- if ((r = ssh_request_reply(sock, msg, msg)) != 0)
+ if ((r = ssh_request_reply_decode(sock, msg)) != 0)
goto out;
- if ((r = sshbuf_get_u8(msg, &type)) != 0)
- goto out;
- r = decode_reply(type);
+ /* success */
+ r = 0;
out:
sshbuf_free(msg);
return r;
@@ -534,11 +552,11 @@ ssh_add_identity_constrained(int sock, struct sshkey *key,
* This call is intended only for use by ssh-add(1) and like applications.
*/
int
-ssh_remove_identity(int sock, struct sshkey *key)
+ssh_remove_identity(int sock, const struct sshkey *key)
{
struct sshbuf *msg;
int r;
- u_char type, *blob = NULL;
+ u_char *blob = NULL;
size_t blen;
if ((msg = sshbuf_new()) == NULL)
@@ -555,11 +573,10 @@ ssh_remove_identity(int sock, struct sshkey *key)
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
- if ((r = ssh_request_reply(sock, msg, msg)) != 0)
+ if ((r = ssh_request_reply_decode(sock, msg)) != 0)
goto out;
- if ((r = sshbuf_get_u8(msg, &type)) != 0)
- goto out;
- r = decode_reply(type);
+ /* success */
+ r = 0;
out:
if (blob != NULL)
freezero(blob, blen);
@@ -595,11 +612,10 @@ ssh_update_card(int sock, int add, const char *reader_id, const char *pin,
if (constrained &&
(r = encode_constraints(msg, life, confirm, 0, NULL)) != 0)
goto out;
- if ((r = ssh_request_reply(sock, msg, msg)) != 0)
+ if ((r = ssh_request_reply_decode(sock, msg)) != 0)
goto out;
- if ((r = sshbuf_get_u8(msg, &type)) != 0)
- goto out;
- r = decode_reply(type);
+ /* success */
+ r = 0;
out:
sshbuf_free(msg);
return r;
@@ -626,11 +642,10 @@ ssh_remove_all_identities(int sock, int version)
return SSH_ERR_ALLOC_FAIL;
if ((r = sshbuf_put_u8(msg, type)) != 0)
goto out;
- if ((r = ssh_request_reply(sock, msg, msg)) != 0)
+ if ((r = ssh_request_reply_decode(sock, msg)) != 0)
goto out;
- if ((r = sshbuf_get_u8(msg, &type)) != 0)
- goto out;
- r = decode_reply(type);
+ /* success */
+ r = 0;
out:
sshbuf_free(msg);
return r;
diff --git a/authfd.h b/authfd.h
index c3bf6259a..4fbf82f8c 100644
--- a/authfd.h
+++ b/authfd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfd.h,v 1.48 2019/12/21 02:19:13 djm Exp $ */
+/* $OpenBSD: authfd.h,v 1.49 2020/06/26 05:03:36 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -33,8 +33,8 @@ 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);
-int ssh_agent_has_key(int sock, struct sshkey *key);
-int ssh_remove_identity(int sock, struct sshkey *key);
+int ssh_agent_has_key(int sock, const struct sshkey *key);
+int ssh_remove_identity(int sock, const struct sshkey *key);
int ssh_update_card(int sock, int add, const char *reader_id,
const char *pin, u_int life, u_int confirm);
int ssh_remove_all_identities(int sock, int version);
diff --git a/authfile.c b/authfile.c
index 35ccf576c..946f50ca8 100644
--- a/authfile.c
+++ b/authfile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfile.c,v 1.140 2020/04/17 07:15:11 djm Exp $ */
+/* $OpenBSD: authfile.c,v 1.141 2020/06/18 23:33:38 djm Exp $ */
/*
* Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
*
@@ -263,7 +263,7 @@ int
sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp)
{
char *pubfile = NULL;
- int r;
+ int r, oerrno;
if (keyp != NULL)
*keyp = NULL;
@@ -283,8 +283,14 @@ sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp)
if ((r = sshkey_load_pubkey_from_private(filename, keyp)) == 0)
goto out;
+ /* Pretend we couldn't find the key */
+ r = SSH_ERR_SYSTEM_ERROR;
+ errno = ENOENT;
+
out:
+ oerrno = errno;
free(pubfile);
+ errno = oerrno;
return r;
}
diff --git a/buildpkg.sh.in b/buildpkg.sh.in
index 4ccc5f8d1..15555cd7e 100644
--- a/buildpkg.sh.in
+++ b/buildpkg.sh.in
@@ -268,7 +268,7 @@ then
touch space
else
cat > space << _EOF
-# extra space required by start/stop links added by installf
+# extra space required by start/stop links added by installf
# in postinstall
$TEST_DIR/etc/rc0.d/${SYSVINITSTOPT}${SYSVINIT_NAME} 0 1
$TEST_DIR/etc/rc2.d/${SYSVINITSTART}${SYSVINIT_NAME} 0 1
@@ -293,7 +293,7 @@ cat >> preinstall << _EOF
#
if [ "\${PRE_INS_STOP}" = "yes" ]
then
- if [ $DO_SMF -eq 1 ]
+ if [ $DO_SMF -eq 1 ]
then
svcadm disable $OPENSSH_FMRI
else
@@ -326,7 +326,7 @@ cat > postinstall << _EOF
if [ $DO_SMF -eq 1 ]
then
- # Delete the existing service, if it exists, then import the
+ # Delete the existing service, if it exists, then import the
# new one.
if svcs $OPENSSH_FMRI > /dev/null 2>&1
then
@@ -438,7 +438,7 @@ echo "Building preremove file..."
cat > preremove << _EOF
#! ${SCRIPT_SHELL}
#
-if [ $DO_SMF -eq 1 ]
+if [ $DO_SMF -eq 1 ]
then
svcadm disable $OPENSSH_FMRI
else
diff --git a/canohost.c b/canohost.c
index abea9c6e6..a810da0ee 100644
--- a/canohost.c
+++ b/canohost.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: canohost.c,v 1.74 2019/06/28 13:35:04 deraadt Exp $ */
+/* $OpenBSD: canohost.c,v 1.75 2020/10/18 11:32:01 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -96,7 +96,7 @@ get_socket_address(int sock, int remote, int flags)
/* Get the address in ascii. */
if ((r = getnameinfo((struct sockaddr *)&addr, addrlen, ntop,
sizeof(ntop), NULL, 0, flags)) != 0) {
- error("%s: getnameinfo %d failed: %s", __func__,
+ error_f("getnameinfo %d failed: %s",
flags, ssh_gai_strerror(r));
return NULL;
}
@@ -141,7 +141,7 @@ get_local_name(int fd)
/* Handle the case where we were passed a pipe */
if (gethostname(myname, sizeof(myname)) == -1) {
- verbose("%s: gethostname: %s", __func__, strerror(errno));
+ verbose_f("gethostname: %s", strerror(errno));
host = xstrdup("UNKNOWN");
} else {
host = xstrdup(myname);
@@ -186,7 +186,7 @@ get_sock_port(int sock, int local)
/* Return port number. */
if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
strport, sizeof(strport), NI_NUMERICSERV)) != 0)
- fatal("%s: getnameinfo NI_NUMERICSERV failed: %s", __func__,
+ fatal_f("getnameinfo NI_NUMERICSERV failed: %s",
ssh_gai_strerror(r));
return atoi(strport);
}
diff --git a/chacha.h b/chacha.h
index 762052565..19a61e294 100644
--- a/chacha.h
+++ b/chacha.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: chacha.h,v 1.4 2016/08/27 04:04:56 guenther Exp $ */
+/* $OpenBSD: chacha.h,v 1.5 2021/04/03 05:54:14 djm Exp $ */
/*
chacha-merged.c version 20080118
@@ -16,7 +16,7 @@ struct chacha_ctx {
u_int input[16];
};
-#define CHACHA_MINKEYLEN 16
+#define CHACHA_MINKEYLEN 16
#define CHACHA_NONCELEN 8
#define CHACHA_CTRLEN 8
#define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN)
diff --git a/channels.c b/channels.c
index 95a51e21b..1c714c845 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.c,v 1.398 2020/04/25 06:59:36 dtucker Exp $ */
+/* $OpenBSD: channels.c,v 1.408 2021/09/14 11:04:21 mbuhl Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -228,7 +228,7 @@ channel_init_channels(struct ssh *ssh)
struct ssh_channels *sc;
if ((sc = calloc(1, sizeof(*sc))) == NULL)
- fatal("%s: allocation failed", __func__);
+ fatal_f("allocation failed");
sc->channels_alloc = 10;
sc->channels = xcalloc(sc->channels_alloc, sizeof(*sc->channels));
sc->IPv4or6 = AF_UNSPEC;
@@ -243,12 +243,12 @@ channel_by_id(struct ssh *ssh, int id)
Channel *c;
if (id < 0 || (u_int)id >= ssh->chanctxt->channels_alloc) {
- logit("%s: %d: bad id", __func__, id);
+ logit_f("%d: bad id", id);
return NULL;
}
c = ssh->chanctxt->channels[id];
if (c == NULL) {
- logit("%s: %d: bad id: channel free", __func__, id);
+ logit_f("%d: bad id: channel free", id);
return NULL;
}
return c;
@@ -333,7 +333,27 @@ channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd,
#endif
/* enable nonblocking mode */
- if (nonblock) {
+ c->restore_block = 0;
+ if (nonblock == CHANNEL_NONBLOCK_STDIO) {
+ /*
+ * Special handling for stdio file descriptors: do not set
+ * non-blocking mode if they are TTYs. Otherwise prepare to
+ * restore their blocking state on exit to avoid interfering
+ * with other programs that follow.
+ */
+ if (rfd != -1 && !isatty(rfd) && fcntl(rfd, F_GETFL) == 0) {
+ c->restore_block |= CHANNEL_RESTORE_RFD;
+ set_nonblock(rfd);
+ }
+ if (wfd != -1 && !isatty(wfd) && fcntl(wfd, F_GETFL) == 0) {
+ c->restore_block |= CHANNEL_RESTORE_WFD;
+ set_nonblock(wfd);
+ }
+ if (efd != -1 && !isatty(efd) && fcntl(efd, F_GETFL) == 0) {
+ c->restore_block |= CHANNEL_RESTORE_EFD;
+ set_nonblock(efd);
+ }
+ } else if (nonblock) {
if (rfd != -1)
set_nonblock(rfd);
if (wfd != -1)
@@ -354,6 +374,7 @@ channel_new(struct ssh *ssh, char *ctype, int type, int rfd, int wfd, int efd,
struct ssh_channels *sc = ssh->chanctxt;
u_int i, found;
Channel *c;
+ int r;
/* Try to find a free slot where to put the new channel. */
for (i = 0; i < sc->channels_alloc; i++) {
@@ -370,8 +391,8 @@ channel_new(struct ssh *ssh, char *ctype, int type, int rfd, int wfd, int efd,
*/
found = sc->channels_alloc;
if (sc->channels_alloc > CHANNELS_MAX_CHANNELS)
- fatal("%s: internal error: channels_alloc %d too big",
- __func__, sc->channels_alloc);
+ fatal_f("internal error: channels_alloc %d too big",
+ sc->channels_alloc);
sc->channels = xrecallocarray(sc->channels, sc->channels_alloc,
sc->channels_alloc + 10, sizeof(*sc->channels));
sc->channels_alloc += 10;
@@ -382,7 +403,9 @@ channel_new(struct ssh *ssh, char *ctype, int type, int rfd, int wfd, int efd,
if ((c->input = sshbuf_new()) == NULL ||
(c->output = sshbuf_new()) == NULL ||
(c->extended = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
+ if ((r = sshbuf_set_max_size(c->input, CHAN_INPUT_MAX)) != 0)
+ fatal_fr(r, "sshbuf_set_max_size");
c->ostate = CHAN_OUTPUT_OPEN;
c->istate = CHAN_INPUT_OPEN;
channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, 0);
@@ -419,17 +442,23 @@ channel_find_maxfd(struct ssh_channels *sc)
}
int
-channel_close_fd(struct ssh *ssh, int *fdp)
+channel_close_fd(struct ssh *ssh, Channel *c, int *fdp)
{
struct ssh_channels *sc = ssh->chanctxt;
- int ret = 0, fd = *fdp;
+ int ret, fd = *fdp;
- if (fd != -1) {
- ret = close(fd);
- *fdp = -1;
- if (fd == sc->channel_max_fd)
- channel_find_maxfd(sc);
- }
+ if (fd == -1)
+ return 0;
+
+ if ((*fdp == c->rfd && (c->restore_block & CHANNEL_RESTORE_RFD) != 0) ||
+ (*fdp == c->wfd && (c->restore_block & CHANNEL_RESTORE_WFD) != 0) ||
+ (*fdp == c->efd && (c->restore_block & CHANNEL_RESTORE_EFD) != 0))
+ (void)fcntl(*fdp, F_SETFL, 0); /* restore blocking */
+
+ ret = close(fd);
+ *fdp = -1;
+ if (fd == sc->channel_max_fd)
+ channel_find_maxfd(sc);
return ret;
}
@@ -439,13 +468,13 @@ channel_close_fds(struct ssh *ssh, Channel *c)
{
int sock = c->sock, rfd = c->rfd, wfd = c->wfd, efd = c->efd;
- channel_close_fd(ssh, &c->sock);
+ channel_close_fd(ssh, c, &c->sock);
if (rfd != sock)
- channel_close_fd(ssh, &c->rfd);
+ channel_close_fd(ssh, c, &c->rfd);
if (wfd != sock && wfd != rfd)
- channel_close_fd(ssh, &c->wfd);
+ channel_close_fd(ssh, c, &c->wfd);
if (efd != sock && efd != rfd && efd != wfd)
- channel_close_fd(ssh, &c->efd);
+ channel_close_fd(ssh, c, &c->efd);
}
static void
@@ -489,7 +518,7 @@ permission_set_get(struct ssh *ssh, int where)
return &sc->remote_perms;
break;
default:
- fatal("%s: invalid forwarding direction %d", __func__, where);
+ fatal_f("invalid forwarding direction %d", where);
}
}
@@ -510,7 +539,7 @@ permission_set_get_array(struct ssh *ssh, int who, int where,
*npermpp = &pset->num_permitted_admin;
break;
default:
- fatal("%s: invalid forwarding client %d", __func__, who);
+ fatal_f("invalid forwarding client %d", who);
}
}
@@ -527,7 +556,7 @@ permission_set_add(struct ssh *ssh, int who, int where,
permission_set_get_array(ssh, who, where, &permp, &npermp);
if (*npermp >= INT_MAX)
- fatal("%s: %s overflow", __func__, fwd_ident(who, where));
+ fatal_f("%s overflow", fwd_ident(who, where));
*permp = xrecallocarray(*permp, *npermp, *npermp + 1, sizeof(**permp));
n = (*npermp)++;
@@ -567,8 +596,7 @@ mux_remove_remote_forwardings(struct ssh *ssh, Channel *c)
channel_rfwd_bind_host(perm->listen_host))) != 0 ||
(r = sshpkt_put_u32(ssh, perm->listen_port)) != 0 ||
(r = sshpkt_send(ssh)) != 0) {
- fatal("%s: channel %i: %s", __func__,
- c->self, ssh_err(r));
+ fatal_fr(r, "channel %i", c->self);
}
fwd_perm_clear(perm); /* unregister */
}
@@ -601,8 +629,14 @@ channel_free(struct ssh *ssh, Channel *c)
debug("channel %d: free: %s, nchannels %u", c->self,
c->remote_name ? c->remote_name : "???", n);
- if (c->type == SSH_CHANNEL_MUX_CLIENT)
+ if (c->type == SSH_CHANNEL_MUX_CLIENT) {
mux_remove_remote_forwardings(ssh, c);
+ free(c->mux_ctx);
+ c->mux_ctx = NULL;
+ } else if (c->type == SSH_CHANNEL_MUX_LISTENER) {
+ free(c->mux_ctx);
+ c->mux_ctx = NULL;
+ }
if (log_level_get() >= SYSLOG_LEVEL_DEBUG3) {
s = channel_open_message(ssh);
@@ -696,7 +730,7 @@ channel_stop_listening(struct ssh *ssh)
case SSH_CHANNEL_X11_LISTENER:
case SSH_CHANNEL_UNIX_LISTENER:
case SSH_CHANNEL_RUNIX_LISTENER:
- channel_close_fd(ssh, &c->sock);
+ channel_close_fd(ssh, c, &c->sock);
channel_free(ssh, c);
break;
}
@@ -764,7 +798,7 @@ channel_still_open(struct ssh *ssh)
case SSH_CHANNEL_MUX_PROXY:
return 1;
default:
- fatal("%s: bad channel type %d", __func__, c->type);
+ fatal_f("bad channel type %d", c->type);
/* NOTREACHED */
}
}
@@ -806,7 +840,7 @@ channel_find_open(struct ssh *ssh)
case SSH_CHANNEL_X11_OPEN:
return i;
default:
- fatal("%s: bad channel type %d", __func__, c->type);
+ fatal_f("bad channel type %d", c->type);
/* NOTREACHED */
}
}
@@ -863,10 +897,10 @@ channel_open_message(struct ssh *ssh)
char *cp, *ret;
if ((buf = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_putf(buf,
"The following connections are open:\r\n")) != 0)
- fatal("%s: sshbuf_putf: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_putf");
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {
c = ssh->chanctxt->channels[i];
if (c == NULL)
@@ -897,18 +931,17 @@ channel_open_message(struct ssh *ssh)
if ((r = sshbuf_putf(buf, " #%d %.300s (%s)\r\n",
c->self, c->remote_name, cp)) != 0) {
free(cp);
- fatal("%s: sshbuf_putf: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_putf");
}
free(cp);
continue;
default:
- fatal("%s: bad channel type %d", __func__, c->type);
+ fatal_f("bad channel type %d", c->type);
/* NOTREACHED */
}
}
if ((ret = sshbuf_dup_string(buf)) == NULL)
- fatal("%s: sshbuf_dup_string", __func__);
+ fatal_f("sshbuf_dup_string");
sshbuf_free(buf);
return ret;
}
@@ -923,7 +956,7 @@ open_preamble(struct ssh *ssh, const char *where, Channel *c, const char *type)
(r = sshpkt_put_u32(ssh, c->self)) != 0 ||
(r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
(r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) {
- fatal("%s: channel %i: open: %s", where, c->self, ssh_err(r));
+ fatal_r(r, "%s: channel %i: open", where, c->self);
}
}
@@ -940,7 +973,7 @@ channel_send_open(struct ssh *ssh, int id)
debug2("channel %d: send open", id);
open_preamble(ssh, __func__, c, c->ctype);
if ((r = sshpkt_send(ssh)) != 0)
- fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r));
+ fatal_fr(r, "channel %i", c->self);
}
void
@@ -950,18 +983,18 @@ channel_request_start(struct ssh *ssh, int id, char *service, int wantconfirm)
int r;
if (c == NULL) {
- logit("%s: %d: unknown channel id", __func__, id);
+ logit_f("%d: unknown channel id", id);
return;
}
if (!c->have_remote_id)
- fatal(":%s: channel %d: no remote id", __func__, c->self);
+ fatal_f("channel %d: no remote id", c->self);
debug2("channel %d: request %s confirm %d", id, service, wantconfirm);
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_cstring(ssh, service)) != 0 ||
(r = sshpkt_put_u8(ssh, wantconfirm)) != 0) {
- fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r));
+ fatal_fr(r, "channel %i", c->self);
}
}
@@ -973,7 +1006,7 @@ channel_register_status_confirm(struct ssh *ssh, int id,
Channel *c;
if ((c = channel_lookup(ssh, id)) == NULL)
- fatal("%s: %d: bad id", __func__, id);
+ fatal_f("%d: bad id", id);
cc = xcalloc(1, sizeof(*cc));
cc->cb = cb;
@@ -989,7 +1022,7 @@ channel_register_open_confirm(struct ssh *ssh, int id,
Channel *c = channel_lookup(ssh, id);
if (c == NULL) {
- logit("%s: %d: bad id", __func__, id);
+ logit_f("%d: bad id", id);
return;
}
c->open_confirm = fn;
@@ -1003,7 +1036,7 @@ channel_register_cleanup(struct ssh *ssh, int id,
Channel *c = channel_by_id(ssh, id);
if (c == NULL) {
- logit("%s: %d: bad id", __func__, id);
+ logit_f("%d: bad id", id);
return;
}
c->detach_user = fn;
@@ -1016,7 +1049,7 @@ channel_cancel_cleanup(struct ssh *ssh, int id)
Channel *c = channel_by_id(ssh, id);
if (c == NULL) {
- logit("%s: %d: bad id", __func__, id);
+ logit_f("%d: bad id", id);
return;
}
c->detach_user = NULL;
@@ -1030,7 +1063,7 @@ channel_register_filter(struct ssh *ssh, int id, channel_infilter_fn *ifn,
Channel *c = channel_lookup(ssh, id);
if (c == NULL) {
- logit("%s: %d: bad id", __func__, id);
+ logit_f("%d: bad id", id);
return;
}
c->input_filter = ifn;
@@ -1049,7 +1082,7 @@ channel_set_fds(struct ssh *ssh, int id, int rfd, int wfd, int efd,
if (c == NULL || c->type != SSH_CHANNEL_LARVAL)
fatal("channel_activate for non-larval channel %d.", id);
if (!c->have_remote_id)
- fatal(":%s: channel %d: no remote id", __func__, c->self);
+ fatal_f("channel %d: no remote id", c->self);
channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, is_tty);
c->type = SSH_CHANNEL_OPEN;
@@ -1059,7 +1092,7 @@ channel_set_fds(struct ssh *ssh, int id, int rfd, int wfd, int efd,
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r));
+ fatal_fr(r, "channel %i", c->self);
}
static void
@@ -1288,24 +1321,21 @@ channel_decode_socks4(Channel *c, struct sshbuf *input, struct sshbuf *output)
(r = sshbuf_get(input, &s4_req.command, 1)) != 0 ||
(r = sshbuf_get(input, &s4_req.dest_port, 2)) != 0 ||
(r = sshbuf_get(input, &s4_req.dest_addr, 4)) != 0) {
- debug("channels %d: decode socks4: %s", c->self, ssh_err(r));
+ debug_r(r, "channels %d: decode socks4", c->self);
return -1;
}
have = sshbuf_len(input);
p = sshbuf_ptr(input);
if (memchr(p, '\0', have) == NULL) {
- error("channel %d: decode socks4: user not nul terminated",
- c->self);
+ error("channel %d: decode socks4: unterminated user", c->self);
return -1;
}
len = strlen(p);
debug2("channel %d: decode socks4: user %s/%d", c->self, p, len);
len++; /* trailing '\0' */
strlcpy(username, p, sizeof(username));
- if ((r = sshbuf_consume(input, len)) != 0) {
- fatal("%s: channel %d: consume: %s", __func__,
- c->self, ssh_err(r));
- }
+ if ((r = sshbuf_consume(input, len)) != 0)
+ fatal_fr(r, "channel %d: consume", c->self);
free(c->path);
c->path = NULL;
if (need == 1) { /* SOCKS4: one string */
@@ -1329,10 +1359,8 @@ channel_decode_socks4(Channel *c, struct sshbuf *input, struct sshbuf *output)
return -1;
}
c->path = xstrdup(p);
- if ((r = sshbuf_consume(input, len)) != 0) {
- fatal("%s: channel %d: consume: %s", __func__,
- c->self, ssh_err(r));
- }
+ if ((r = sshbuf_consume(input, len)) != 0)
+ fatal_fr(r, "channel %d: consume", c->self);
}
c->host_port = ntohs(s4_req.dest_port);
@@ -1348,10 +1376,8 @@ channel_decode_socks4(Channel *c, struct sshbuf *input, struct sshbuf *output)
s4_rsp.command = 90; /* cd: req granted */
s4_rsp.dest_port = 0; /* ignored */
s4_rsp.dest_addr.s_addr = INADDR_ANY; /* ignored */
- if ((r = sshbuf_put(output, &s4_rsp, sizeof(s4_rsp))) != 0) {
- fatal("%s: channel %d: append reply: %s", __func__,
- c->self, ssh_err(r));
- }
+ if ((r = sshbuf_put(output, &s4_rsp, sizeof(s4_rsp))) != 0)
+ fatal_fr(r, "channel %d: append reply", c->self);
return 1;
}
@@ -1404,16 +1430,12 @@ channel_decode_socks5(Channel *c, struct sshbuf *input, struct sshbuf *output)
c->self);
return -1;
}
- if ((r = sshbuf_consume(input, nmethods + 2)) != 0) {
- fatal("%s: channel %d: consume: %s", __func__,
- c->self, ssh_err(r));
- }
+ if ((r = sshbuf_consume(input, nmethods + 2)) != 0)
+ fatal_fr(r, "channel %d: consume", c->self);
/* version, method */
if ((r = sshbuf_put_u8(output, 0x05)) != 0 ||
- (r = sshbuf_put_u8(output, SSH_SOCKS5_NOAUTH)) != 0) {
- fatal("%s: channel %d: append reply: %s", __func__,
- c->self, ssh_err(r));
- }
+ (r = sshbuf_put_u8(output, SSH_SOCKS5_NOAUTH)) != 0)
+ fatal_fr(r, "channel %d: append reply", c->self);
c->flags |= SSH_SOCKS5_AUTHDONE;
debug2("channel %d: socks5 auth done", c->self);
return 0; /* need more */
@@ -1450,20 +1472,16 @@ channel_decode_socks5(Channel *c, struct sshbuf *input, struct sshbuf *output)
need++;
if (have < need)
return 0;
- if ((r = sshbuf_consume(input, sizeof(s5_req))) != 0) {
- fatal("%s: channel %d: consume: %s", __func__,
- c->self, ssh_err(r));
- }
+ if ((r = sshbuf_consume(input, sizeof(s5_req))) != 0)
+ fatal_fr(r, "channel %d: consume", c->self);
if (s5_req.atyp == SSH_SOCKS5_DOMAIN) {
/* host string length */
- if ((r = sshbuf_consume(input, 1)) != 0) {
- fatal("%s: channel %d: consume: %s", __func__,
- c->self, ssh_err(r));
- }
+ if ((r = sshbuf_consume(input, 1)) != 0)
+ fatal_fr(r, "channel %d: consume", c->self);
}
if ((r = sshbuf_get(input, &dest_addr, addrlen)) != 0 ||
(r = sshbuf_get(input, &dest_port, 2)) != 0) {
- debug("channel %d: parse addr/port: %s", c->self, ssh_err(r));
+ debug_r(r, "channel %d: parse addr/port", c->self);
return -1;
}
dest_addr[addrlen] = '\0';
@@ -1495,22 +1513,22 @@ channel_decode_socks5(Channel *c, struct sshbuf *input, struct sshbuf *output)
if ((r = sshbuf_put(output, &s5_rsp, sizeof(s5_rsp))) != 0 ||
(r = sshbuf_put_u32(output, ntohl(INADDR_ANY))) != 0 ||
(r = sshbuf_put(output, &dest_port, sizeof(dest_port))) != 0)
- fatal("%s: channel %d: append reply: %s", __func__,
- c->self, ssh_err(r));
+ fatal_fr(r, "channel %d: append reply", c->self);
return 1;
}
Channel *
channel_connect_stdio_fwd(struct ssh *ssh,
- const char *host_to_connect, u_short port_to_connect, int in, int out)
+ const char *host_to_connect, u_short port_to_connect,
+ int in, int out, int nonblock)
{
Channel *c;
- debug("%s %s:%d", __func__, host_to_connect, port_to_connect);
+ debug_f("%s:%d", host_to_connect, port_to_connect);
c = channel_new(ssh, "stdio-forward", SSH_CHANNEL_OPENING, in, out,
-1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
- 0, "stdio-forward", /*nonblock*/0);
+ 0, "stdio-forward", nonblock);
c->path = xstrdup(host_to_connect);
c->host_port = port_to_connect;
@@ -1595,10 +1613,8 @@ channel_before_prepare_select_rdynamic(struct ssh *ssh, Channel *c)
/* sshbuf_dump(c->output, stderr); */
/* EOF received */
if (c->flags & CHAN_EOF_RCVD) {
- if ((r = sshbuf_consume(c->output, have)) != 0) {
- fatal("%s: channel %d: consume: %s",
- __func__, c->self, ssh_err(r));
- }
+ if ((r = sshbuf_consume(c->output, have)) != 0)
+ fatal_fr(r, "channel %d: consume", c->self);
rdynamic_close(ssh, c);
return;
}
@@ -1630,13 +1646,10 @@ channel_before_prepare_select_rdynamic(struct ssh *ssh, Channel *c)
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_stringb(ssh, c->input)) != 0 ||
(r = sshpkt_send(ssh)) != 0) {
- fatal("%s: channel %i: rdynamic: %s", __func__,
- c->self, ssh_err(r));
- }
- if ((r = sshbuf_consume(c->input, len)) != 0) {
- fatal("%s: channel %d: consume: %s",
- __func__, c->self, ssh_err(r));
+ fatal_fr(r, "channel %i: rdynamic", c->self);
}
+ if ((r = sshbuf_consume(c->input, len)) != 0)
+ fatal_fr(r, "channel %d: consume", c->self);
c->remote_window -= len;
}
} else if (rdynamic_connect_finish(ssh, c) < 0) {
@@ -1665,7 +1678,7 @@ channel_post_x11_listener(struct ssh *ssh, Channel *c,
if (c->single_connection) {
oerrno = errno;
debug2("single_connection: closing X11 listener.");
- channel_close_fd(ssh, &c->sock);
+ channel_close_fd(ssh, c, &c->sock);
chan_mark_dead(ssh, c);
errno = oerrno;
}
@@ -1689,11 +1702,10 @@ channel_post_x11_listener(struct ssh *ssh, Channel *c,
open_preamble(ssh, __func__, nc, "x11");
if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0 ||
(r = sshpkt_put_u32(ssh, remote_port)) != 0) {
- fatal("%s: channel %i: reply %s", __func__,
- c->self, ssh_err(r));
+ fatal_fr(r, "channel %i: reply", c->self);
}
if ((r = sshpkt_send(ssh)) != 0)
- fatal("%s: channel %i: send %s", __func__, c->self, ssh_err(r));
+ fatal_fr(r, "channel %i: send", c->self);
free(remote_ipaddr);
}
@@ -1724,46 +1736,34 @@ port_open_helper(struct ssh *ssh, Channel *c, char *rtype)
if (strcmp(rtype, "direct-tcpip") == 0) {
/* target host, port */
if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 ||
- (r = sshpkt_put_u32(ssh, c->host_port)) != 0) {
- fatal("%s: channel %i: reply %s", __func__,
- c->self, ssh_err(r));
- }
+ (r = sshpkt_put_u32(ssh, c->host_port)) != 0)
+ fatal_fr(r, "channel %i: reply", c->self);
} else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) {
/* target path */
- if ((r = sshpkt_put_cstring(ssh, c->path)) != 0) {
- fatal("%s: channel %i: reply %s", __func__,
- c->self, ssh_err(r));
- }
+ if ((r = sshpkt_put_cstring(ssh, c->path)) != 0)
+ fatal_fr(r, "channel %i: reply", c->self);
} else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
/* listen path */
- if ((r = sshpkt_put_cstring(ssh, c->path)) != 0) {
- fatal("%s: channel %i: reply %s", __func__,
- c->self, ssh_err(r));
- }
+ if ((r = sshpkt_put_cstring(ssh, c->path)) != 0)
+ fatal_fr(r, "channel %i: reply", c->self);
} else {
/* listen address, port */
if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 ||
- (r = sshpkt_put_u32(ssh, local_port)) != 0) {
- fatal("%s: channel %i: reply %s", __func__,
- c->self, ssh_err(r));
- }
+ (r = sshpkt_put_u32(ssh, local_port)) != 0)
+ fatal_fr(r, "channel %i: reply", c->self);
}
if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
/* reserved for future owner/mode info */
- if ((r = sshpkt_put_cstring(ssh, "")) != 0) {
- fatal("%s: channel %i: reply %s", __func__,
- c->self, ssh_err(r));
- }
+ if ((r = sshpkt_put_cstring(ssh, "")) != 0)
+ fatal_fr(r, "channel %i: reply", c->self);
} else {
/* originator host and port */
if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0 ||
- (r = sshpkt_put_u32(ssh, (u_int)remote_port)) != 0) {
- fatal("%s: channel %i: reply %s", __func__,
- c->self, ssh_err(r));
- }
+ (r = sshpkt_put_u32(ssh, (u_int)remote_port)) != 0)
+ fatal_fr(r, "channel %i: reply", c->self);
}
if ((r = sshpkt_send(ssh)) != 0)
- fatal("%s: channel %i: send %s", __func__, c->self, ssh_err(r));
+ fatal_fr(r, "channel %i: send", c->self);
free(remote_ipaddr);
free(local_ipaddr);
}
@@ -1863,7 +1863,7 @@ channel_post_auth_listener(struct ssh *ssh, Channel *c,
0, "accepted auth socket", 1);
open_preamble(ssh, __func__, nc, "auth-agent@openssh.com");
if ((r = sshpkt_send(ssh)) != 0)
- fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r));
+ fatal_fr(r, "channel %i", c->self);
}
static void
@@ -1876,7 +1876,7 @@ channel_post_connecting(struct ssh *ssh, Channel *c,
if (!FD_ISSET(c->sock, writeset))
return;
if (!c->have_remote_id)
- fatal(":%s: channel %d: no remote id", __func__, c->self);
+ fatal_f("channel %d: no remote id", c->self);
/* for rdynamic the OPEN_CONFIRMATION has been sent already */
isopen = (c->type == SSH_CHANNEL_RDYNAMIC_FINISH);
if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) == -1) {
@@ -1896,13 +1896,9 @@ channel_post_connecting(struct ssh *ssh, Channel *c,
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_u32(ssh, c->self)) != 0 ||
(r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
- (r = sshpkt_put_u32(ssh, c->local_maxpacket))
- != 0)
- fatal("%s: channel %i: confirm: %s", __func__,
- c->self, ssh_err(r));
- if ((r = sshpkt_send(ssh)) != 0)
- fatal("%s: channel %i: %s", __func__, c->self,
- ssh_err(r));
+ (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal_fr(r, "channel %i open confirm", c->self);
}
} else {
debug("channel %d: connection failed: %s",
@@ -1927,13 +1923,9 @@ channel_post_connecting(struct ssh *ssh, Channel *c,
(r = sshpkt_put_u32(ssh,
SSH2_OPEN_CONNECT_FAILED)) != 0 ||
(r = sshpkt_put_cstring(ssh, strerror(err))) != 0 ||
- (r = sshpkt_put_cstring(ssh, "")) != 0) {
- fatal("%s: channel %i: failure: %s", __func__,
- c->self, ssh_err(r));
- }
- if ((r = sshpkt_send(ssh)) != 0)
- fatal("%s: channel %i: %s", __func__, c->self,
- ssh_err(r));
+ (r = sshpkt_put_cstring(ssh, "")) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal_fr(r, "channel %i: failure", c->self);
chan_mark_dead(ssh, c);
}
}
@@ -1958,7 +1950,7 @@ channel_handle_rfd(struct ssh *ssh, Channel *c,
((errno == EAGAIN || errno == EWOULDBLOCK) && !force)))
return 1;
#ifndef PTY_ZEROREAD
- if (len <= 0) {
+ if (len <= 0) {
#else
if ((!c->isatty && len <= 0) ||
(c->isatty && (len < 0 || (len == 0 && errno != 0)))) {
@@ -1981,12 +1973,9 @@ channel_handle_rfd(struct ssh *ssh, Channel *c,
}
} else if (c->datagram) {
if ((r = sshbuf_put_string(c->input, buf, len)) != 0)
- fatal("%s: channel %d: put datagram: %s", __func__,
- c->self, ssh_err(r));
- } else if ((r = sshbuf_put(c->input, buf, len)) != 0) {
- fatal("%s: channel %d: put data: %s", __func__,
- c->self, ssh_err(r));
- }
+ fatal_fr(r, "channel %i: put datagram", c->self);
+ } else if ((r = sshbuf_put(c->input, buf, len)) != 0)
+ fatal_fr(r, "channel %i: put data", c->self);
return 1;
}
@@ -2016,8 +2005,7 @@ channel_handle_wfd(struct ssh *ssh, Channel *c,
}
} else if (c->datagram) {
if ((r = sshbuf_get_string(c->output, &data, &dlen)) != 0)
- fatal("%s: channel %d: get datagram: %s", __func__,
- c->self, ssh_err(r));
+ fatal_fr(r, "channel %i: get datagram", c->self);
buf = data;
} else {
buf = data = sshbuf_mutable_ptr(c->output);
@@ -2069,15 +2057,12 @@ channel_handle_wfd(struct ssh *ssh, Channel *c,
*/
if ((r = sshpkt_msg_ignore(ssh, 4+len)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: channel %d: ignore: %s",
- __func__, c->self, ssh_err(r));
+ fatal_fr(r, "channel %i: ignore", c->self);
}
}
#endif /* BROKEN_TCGETATTR_ICANON */
- if ((r = sshbuf_consume(c->output, len)) != 0) {
- fatal("%s: channel %d: consume: %s",
- __func__, c->self, ssh_err(r));
- }
+ if ((r = sshbuf_consume(c->output, len)) != 0)
+ fatal_fr(r, "channel %i: consume", c->self);
out:
c->local_consumed += olen - sshbuf_len(c->output);
@@ -2102,12 +2087,10 @@ channel_handle_efd_write(struct ssh *ssh, Channel *c,
return 1;
if (len <= 0) {
debug2("channel %d: closing write-efd %d", c->self, c->efd);
- channel_close_fd(ssh, &c->efd);
+ channel_close_fd(ssh, c, &c->efd);
} else {
- if ((r = sshbuf_consume(c->extended, len)) != 0) {
- fatal("%s: channel %d: consume: %s",
- __func__, c->self, ssh_err(r));
- }
+ if ((r = sshbuf_consume(c->extended, len)) != 0)
+ fatal_fr(r, "channel %i: consume", c->self);
c->local_consumed += len;
}
return 1;
@@ -2132,18 +2115,12 @@ channel_handle_efd_read(struct ssh *ssh, Channel *c,
errno == EWOULDBLOCK) && !force)))
return 1;
if (len <= 0) {
- debug2("channel %d: closing read-efd %d",
- c->self, c->efd);
- channel_close_fd(ssh, &c->efd);
- } else {
- if (c->extended_usage == CHAN_EXTENDED_IGNORE) {
- debug3("channel %d: discard efd",
- c->self);
- } else if ((r = sshbuf_put(c->extended, buf, len)) != 0) {
- fatal("%s: channel %d: append: %s",
- __func__, c->self, ssh_err(r));
- }
- }
+ debug2("channel %d: closing read-efd %d", c->self, c->efd);
+ channel_close_fd(ssh, c, &c->efd);
+ } else if (c->extended_usage == CHAN_EXTENDED_IGNORE)
+ debug3("channel %d: discard efd", c->self);
+ else if ((r = sshbuf_put(c->extended, buf, len)) != 0)
+ fatal_fr(r, "channel %i: append", c->self);
return 1;
}
@@ -2177,19 +2154,16 @@ channel_check_window(struct ssh *ssh, Channel *c)
c->local_window < c->local_window_max/2) &&
c->local_consumed > 0) {
if (!c->have_remote_id)
- fatal(":%s: channel %d: no remote id",
- __func__, c->self);
+ fatal_f("channel %d: no remote id", c->self);
if ((r = sshpkt_start(ssh,
SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_u32(ssh, c->local_consumed)) != 0 ||
(r = sshpkt_send(ssh)) != 0) {
- fatal("%s: channel %i: %s", __func__,
- c->self, ssh_err(r));
+ fatal_fr(r, "channel %i", c->self);
}
- debug2("channel %d: window %d sent adjust %d",
- c->self, c->local_window,
- c->local_consumed);
+ debug2("channel %d: window %d sent adjust %d", c->self,
+ c->local_window, c->local_consumed);
c->local_window += c->local_consumed;
c->local_consumed = 0;
}
@@ -2224,10 +2198,8 @@ read_mux(struct ssh *ssh, Channel *c, u_int need)
c->self, c->rfd, len);
chan_read_failed(ssh, c);
return 0;
- } else if ((r = sshbuf_put(c->input, buf, len)) != 0) {
- fatal("%s: channel %d: append: %s",
- __func__, c->self, ssh_err(r));
- }
+ } else if ((r = sshbuf_put(c->input, buf, len)) != 0)
+ fatal_fr(r, "channel %i: append", c->self);
}
return sshbuf_len(c->input);
}
@@ -2288,8 +2260,7 @@ channel_post_mux_client_write(struct ssh *ssh, Channel *c,
return;
}
if ((r = sshbuf_consume(c->output, len)) != 0)
- fatal("%s: channel %d: consume: %s", __func__,
- c->self, ssh_err(r));
+ fatal_fr(r, "channel %i: consume", c->self);
}
static void
@@ -2323,15 +2294,14 @@ channel_post_mux_listener(struct ssh *ssh, Channel *c,
addrlen = sizeof(addr);
if ((newsock = accept(c->sock, (struct sockaddr*)&addr,
&addrlen)) == -1) {
- error("%s accept: %s", __func__, strerror(errno));
+ error_f("accept: %s", strerror(errno));
if (errno == EMFILE || errno == ENFILE)
c->notbefore = monotime() + 1;
return;
}
if (getpeereid(newsock, &euid, &egid) == -1) {
- error("%s getpeereid failed: %s", __func__,
- strerror(errno));
+ error_f("getpeereid failed: %s", strerror(errno));
close(newsock);
return;
}
@@ -2345,7 +2315,7 @@ channel_post_mux_listener(struct ssh *ssh, Channel *c,
newsock, newsock, -1, c->local_window_max,
c->local_maxpacket, 0, "mux-control", 1);
nc->mux_rcb = c->mux_rcb;
- debug3("%s: new mux channel %d fd %d", __func__, nc->self, nc->sock);
+ debug3_f("new mux channel %d fd %d", nc->self, nc->sock);
/* establish state */
nc->mux_rcb(ssh, nc);
/* mux state transitions must not elicit protocol messages */
@@ -2358,8 +2328,8 @@ channel_handler_init(struct ssh_channels *sc)
chan_fn **pre, **post;
if ((pre = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*pre))) == NULL ||
- (post = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*post))) == NULL)
- fatal("%s: allocation failed", __func__);
+ (post = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*post))) == NULL)
+ fatal_f("allocation failed");
pre[SSH_CHANNEL_OPEN] = &channel_pre_open;
pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
@@ -2451,8 +2421,8 @@ channel_handler(struct ssh *ssh, int table,
* Collect the time that the earliest
* channel comes off pause.
*/
- debug3("%s: chan %d: skip for %d more seconds",
- __func__, c->self,
+ debug3_f("chan %d: skip for %d more "
+ "seconds", c->self,
(int)(c->notbefore - now));
if (*unpause_secs == 0 ||
(c->notbefore - now) < *unpause_secs)
@@ -2462,8 +2432,8 @@ channel_handler(struct ssh *ssh, int table,
channel_garbage_collect(ssh, c);
}
if (unpause_secs != NULL && *unpause_secs != 0)
- debug3("%s: first channel unpauses in %d seconds",
- __func__, (int)*unpause_secs);
+ debug3_f("first channel unpauses in %d seconds",
+ (int)*unpause_secs);
}
/*
@@ -2562,13 +2532,12 @@ channel_output_poll_input_open(struct ssh *ssh, Channel *c)
}
if (!c->have_remote_id)
- fatal(":%s: channel %d: no remote id", __func__, c->self);
+ fatal_f("channel %d: no remote id", c->self);
if (c->datagram) {
/* Check datagram will fit; drop if not */
if ((r = sshbuf_get_string_direct(c->input, &pkt, &plen)) != 0)
- fatal("%s: channel %d: get datagram: %s", __func__,
- c->self, ssh_err(r));
+ fatal_fr(r, "channel %i: get datagram", c->self);
/*
* XXX this does tail-drop on the datagram queue which is
* usually suboptimal compared to head-drop. Better to have
@@ -2582,10 +2551,8 @@ channel_output_poll_input_open(struct ssh *ssh, Channel *c)
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_string(ssh, pkt, plen)) != 0 ||
- (r = sshpkt_send(ssh)) != 0) {
- fatal("%s: channel %i: datagram: %s", __func__,
- c->self, ssh_err(r));
- }
+ (r = sshpkt_send(ssh)) != 0)
+ fatal_fr(r, "channel %i: send datagram", c->self);
c->remote_window -= plen;
return;
}
@@ -2600,13 +2567,10 @@ channel_output_poll_input_open(struct ssh *ssh, Channel *c)
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_string(ssh, sshbuf_ptr(c->input), len)) != 0 ||
- (r = sshpkt_send(ssh)) != 0) {
- fatal("%s: channel %i: data: %s", __func__,
- c->self, ssh_err(r));
- }
+ (r = sshpkt_send(ssh)) != 0)
+ fatal_fr(r, "channel %i: send data", c->self);
if ((r = sshbuf_consume(c->input, len)) != 0)
- fatal("%s: channel %i: consume: %s", __func__,
- c->self, ssh_err(r));
+ fatal_fr(r, "channel %i: consume", c->self);
c->remote_window -= len;
}
@@ -2631,18 +2595,15 @@ channel_output_poll_extended_read(struct ssh *ssh, Channel *c)
if (len == 0)
return;
if (!c->have_remote_id)
- fatal(":%s: channel %d: no remote id", __func__, c->self);
+ fatal_f("channel %d: no remote id", c->self);
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_u32(ssh, SSH2_EXTENDED_DATA_STDERR)) != 0 ||
(r = sshpkt_put_string(ssh, sshbuf_ptr(c->extended), len)) != 0 ||
- (r = sshpkt_send(ssh)) != 0) {
- fatal("%s: channel %i: data: %s", __func__,
- c->self, ssh_err(r));
- }
+ (r = sshpkt_send(ssh)) != 0)
+ fatal_fr(r, "channel %i: data", c->self);
if ((r = sshbuf_consume(c->extended, len)) != 0)
- fatal("%s: channel %i: consume: %s", __func__,
- c->self, ssh_err(r));
+ fatal_fr(r, "channel %i: consume", c->self);
c->remote_window -= len;
debug2("channel %d: sent ext data %zu", c->self, len);
}
@@ -2739,11 +2700,11 @@ channel_proxy_downstream(struct ssh *ssh, Channel *downstream)
/* sshbuf_dump(downstream->input, stderr); */
if ((r = sshbuf_get_string_direct(downstream->input, &cp, &have))
!= 0) {
- error("%s: malformed message: %s", __func__, ssh_err(r));
+ error_fr(r, "parse");
return -1;
}
if (have < 2) {
- error("%s: short message", __func__);
+ error_f("short message");
return -1;
}
type = cp[1];
@@ -2751,29 +2712,29 @@ channel_proxy_downstream(struct ssh *ssh, Channel *downstream)
cp += 2;
have -= 2;
if (ssh_packet_log_type(type))
- debug3("%s: channel %u: down->up: type %u", __func__,
+ debug3_f("channel %u: down->up: type %u",
downstream->self, type);
switch (type) {
case SSH2_MSG_CHANNEL_OPEN:
if ((original = sshbuf_from(cp, have)) == NULL ||
(modified = sshbuf_new()) == NULL) {
- error("%s: alloc", __func__);
+ error_f("alloc");
goto out;
}
if ((r = sshbuf_get_cstring(original, &ctype, NULL)) != 0 ||
(r = sshbuf_get_u32(original, &id)) != 0) {
- error("%s: parse error %s", __func__, ssh_err(r));
+ error_fr(r, "parse");
goto out;
}
c = channel_new(ssh, "mux proxy", SSH_CHANNEL_MUX_PROXY,
- -1, -1, -1, 0, 0, 0, ctype, 1);
+ -1, -1, -1, 0, 0, 0, ctype, 1);
c->mux_ctx = downstream; /* point to mux client */
c->mux_downstream_id = id; /* original downstream id */
if ((r = sshbuf_put_cstring(modified, ctype)) != 0 ||
(r = sshbuf_put_u32(modified, c->self)) != 0 ||
(r = sshbuf_putb(modified, original)) != 0) {
- error("%s: compose error %s", __func__, ssh_err(r));
+ error_fr(r, "compose");
channel_free(ssh, c);
goto out;
}
@@ -2785,16 +2746,16 @@ channel_proxy_downstream(struct ssh *ssh, Channel *downstream)
*/
if ((original = sshbuf_from(cp, have)) == NULL ||
(modified = sshbuf_new()) == NULL) {
- error("%s: alloc", __func__);
+ error_f("alloc");
goto out;
}
if ((r = sshbuf_get_u32(original, &remote_id)) != 0 ||
(r = sshbuf_get_u32(original, &id)) != 0) {
- error("%s: parse error %s", __func__, ssh_err(r));
+ error_fr(r, "parse");
goto out;
}
c = channel_new(ssh, "mux proxy", SSH_CHANNEL_MUX_PROXY,
- -1, -1, -1, 0, 0, 0, "mux-down-connect", 1);
+ -1, -1, -1, 0, 0, 0, "mux-down-connect", 1);
c->mux_ctx = downstream; /* point to mux client */
c->mux_downstream_id = id;
c->remote_id = remote_id;
@@ -2802,33 +2763,33 @@ channel_proxy_downstream(struct ssh *ssh, Channel *downstream)
if ((r = sshbuf_put_u32(modified, remote_id)) != 0 ||
(r = sshbuf_put_u32(modified, c->self)) != 0 ||
(r = sshbuf_putb(modified, original)) != 0) {
- error("%s: compose error %s", __func__, ssh_err(r));
+ error_fr(r, "compose");
channel_free(ssh, c);
goto out;
}
break;
case SSH2_MSG_GLOBAL_REQUEST:
if ((original = sshbuf_from(cp, have)) == NULL) {
- error("%s: alloc", __func__);
+ error_f("alloc");
goto out;
}
if ((r = sshbuf_get_cstring(original, &ctype, NULL)) != 0) {
- error("%s: parse error %s", __func__, ssh_err(r));
+ error_fr(r, "parse");
goto out;
}
if (strcmp(ctype, "tcpip-forward") != 0) {
- error("%s: unsupported request %s", __func__, ctype);
+ error_f("unsupported request %s", ctype);
goto out;
}
if ((r = sshbuf_get_u8(original, NULL)) != 0 ||
(r = sshbuf_get_cstring(original, &listen_host, NULL)) != 0 ||
(r = sshbuf_get_u32(original, &listen_port)) != 0) {
- error("%s: parse error %s", __func__, ssh_err(r));
+ error_fr(r, "parse");
goto out;
}
if (listen_port > 65535) {
- error("%s: tcpip-forward for %s: bad port %u",
- __func__, listen_host, listen_port);
+ error_f("tcpip-forward for %s: bad port %u",
+ listen_host, listen_port);
goto out;
}
/* Record that connection to this host/port is permitted. */
@@ -2852,14 +2813,14 @@ channel_proxy_downstream(struct ssh *ssh, Channel *downstream)
if ((r = sshpkt_start(ssh, type)) != 0 ||
(r = sshpkt_putb(ssh, modified)) != 0 ||
(r = sshpkt_send(ssh)) != 0) {
- error("%s: send %s", __func__, ssh_err(r));
+ error_fr(r, "send");
goto out;
}
} else {
if ((r = sshpkt_start(ssh, type)) != 0 ||
(r = sshpkt_put(ssh, cp, have)) != 0 ||
(r = sshpkt_send(ssh)) != 0) {
- error("%s: send %s", __func__, ssh_err(r));
+ error_fr(r, "send");
goto out;
}
}
@@ -2910,18 +2871,17 @@ channel_proxy_upstream(Channel *c, int type, u_int32_t seq, struct ssh *ssh)
case SSH2_MSG_CHANNEL_REQUEST:
break;
default:
- debug2("%s: channel %u: unsupported type %u", __func__,
- c->self, type);
+ debug2_f("channel %u: unsupported type %u", c->self, type);
return 0;
}
if ((b = sshbuf_new()) == NULL) {
- error("%s: alloc reply", __func__);
+ error_f("alloc reply");
goto out;
}
/* get remaining payload (after id) */
cp = sshpkt_ptr(ssh, &len);
if (cp == NULL) {
- error("%s: no packet", __func__);
+ error_f("no packet");
goto out;
}
/* translate id and send to muxclient */
@@ -2930,13 +2890,12 @@ channel_proxy_upstream(Channel *c, int type, u_int32_t seq, struct ssh *ssh)
(r = sshbuf_put_u32(b, c->mux_downstream_id)) != 0 ||
(r = sshbuf_put(b, cp, len)) != 0 ||
(r = sshbuf_put_stringb(downstream->output, b)) != 0) {
- error("%s: compose for muxclient %s", __func__, ssh_err(r));
+ error_fr(r, "compose muxclient");
goto out;
}
/* sshbuf_dump(b, stderr); */
if (ssh_packet_log_type(type))
- debug3("%s: channel %u: up->down: type %u", __func__, c->self,
- type);
+ debug3_f("channel %u: up->down: type %u", c->self, type);
out:
/* update state */
switch (type) {
@@ -2968,11 +2927,11 @@ channel_parse_id(struct ssh *ssh, const char *where, const char *what)
int r;
if ((r = sshpkt_get_u32(ssh, &id)) != 0) {
- error("%s: parse id: %s", where, ssh_err(r));
+ error_r(r, "%s: parse id", where);
ssh_packet_disconnect(ssh, "Invalid %s message", what);
}
if (id > INT_MAX) {
- error("%s: bad channel id %u: %s", where, id, ssh_err(r));
+ error_r(r, "%s: bad channel id %u", where, id);
ssh_packet_disconnect(ssh, "Invalid %s channel id", what);
}
return (int)id;
@@ -3013,8 +2972,7 @@ channel_input_data(int type, u_int32_t seq, struct ssh *ssh)
/* Get the data. */
if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0)
- fatal("%s: channel %d: get data: %s", __func__,
- c->self, ssh_err(r));
+ fatal_fr(r, "channel %i: get data", c->self);
win_len = data_len;
if (c->datagram)
@@ -3045,11 +3003,9 @@ channel_input_data(int type, u_int32_t seq, struct ssh *ssh)
if (c->datagram) {
if ((r = sshbuf_put_string(c->output, data, data_len)) != 0)
- fatal("%s: channel %d: append datagram: %s",
- __func__, c->self, ssh_err(r));
+ fatal_fr(r, "channel %i: append datagram", c->self);
} else if ((r = sshbuf_put(c->output, data, data_len)) != 0)
- fatal("%s: channel %d: append data: %s",
- __func__, c->self, ssh_err(r));
+ fatal_fr(r, "channel %i: append data", c->self);
return 0;
}
@@ -3070,7 +3026,7 @@ channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh)
return 0;
}
if (c->flags & CHAN_EOF_RCVD) {
- if (datafellows & SSH_BUG_EXTEOF)
+ if (ssh->compat & SSH_BUG_EXTEOF)
debug("channel %d: accepting ext data after eof",
c->self);
else
@@ -3079,7 +3035,7 @@ channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh)
}
if ((r = sshpkt_get_u32(ssh, &tcode)) != 0) {
- error("%s: parse tcode: %s", __func__, ssh_err(r));
+ error_fr(r, "parse tcode");
ssh_packet_disconnect(ssh, "Invalid extended_data message");
}
if (c->efd == -1 ||
@@ -3090,7 +3046,7 @@ channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh)
}
if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0) {
- error("%s: parse data: %s", __func__, ssh_err(r));
+ error_fr(r, "parse data");
ssh_packet_disconnect(ssh, "Invalid extended_data message");
}
@@ -3102,7 +3058,7 @@ channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh)
debug2("channel %d: rcvd ext data %zu", c->self, data_len);
/* XXX sshpkt_getb? */
if ((r = sshbuf_put(c->extended, data, data_len)) != 0)
- error("%s: append: %s", __func__, ssh_err(r));
+ error_fr(r, "append");
c->local_window -= data_len;
return 0;
}
@@ -3114,7 +3070,7 @@ channel_input_ieof(int type, u_int32_t seq, struct ssh *ssh)
int r;
if ((r = sshpkt_get_end(ssh)) != 0) {
- error("%s: parse data: %s", __func__, ssh_err(r));
+ error_fr(r, "parse data");
ssh_packet_disconnect(ssh, "Invalid ieof message");
}
@@ -3141,7 +3097,7 @@ channel_input_oclose(int type, u_int32_t seq, struct ssh *ssh)
if (channel_proxy_upstream(c, type, seq, ssh))
return 0;
if ((r = sshpkt_get_end(ssh)) != 0) {
- error("%s: parse data: %s", __func__, ssh_err(r));
+ error_fr(r, "parse data");
ssh_packet_disconnect(ssh, "Invalid oclose message");
}
chan_rcvd_oclose(ssh, c);
@@ -3168,7 +3124,7 @@ channel_input_open_confirmation(int type, u_int32_t seq, struct ssh *ssh)
(r = sshpkt_get_u32(ssh, &remote_window)) != 0 ||
(r = sshpkt_get_u32(ssh, &remote_maxpacket)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0) {
- error("%s: window/maxpacket: %s", __func__, ssh_err(r));
+ error_fr(r, "window/maxpacket");
ssh_packet_disconnect(ssh, "Invalid open confirmation message");
}
@@ -3177,9 +3133,9 @@ channel_input_open_confirmation(int type, u_int32_t seq, struct ssh *ssh)
c->remote_maxpacket = remote_maxpacket;
c->type = SSH_CHANNEL_OPEN;
if (c->open_confirm) {
- debug2("%s: channel %d: callback start", __func__, c->self);
+ debug2_f("channel %d: callback start", c->self);
c->open_confirm(ssh, c->self, 1, c->open_confirm_ctx);
- debug2("%s: channel %d: callback done", __func__, c->self);
+ debug2_f("channel %d: callback done", c->self);
}
debug2("channel %d: open confirm rwindow %u rmax %u", c->self,
c->remote_window, c->remote_maxpacket);
@@ -3216,23 +3172,23 @@ channel_input_open_failure(int type, u_int32_t seq, struct ssh *ssh)
ssh_packet_disconnect(ssh, "Received open failure for "
"non-opening channel %d.", c->self);
if ((r = sshpkt_get_u32(ssh, &reason)) != 0) {
- error("%s: reason: %s", __func__, ssh_err(r));
+ error_fr(r, "parse reason");
ssh_packet_disconnect(ssh, "Invalid open failure message");
}
/* skip language */
if ((r = sshpkt_get_cstring(ssh, &msg, NULL)) != 0 ||
(r = sshpkt_get_string_direct(ssh, NULL, NULL)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0) {
- error("%s: message/lang: %s", __func__, ssh_err(r));
+ error_fr(r, "parse msg/lang");
ssh_packet_disconnect(ssh, "Invalid open failure message");
}
logit("channel %d: open failed: %s%s%s", c->self,
reason2txt(reason), msg ? ": ": "", msg ? msg : "");
free(msg);
if (c->open_confirm) {
- debug2("%s: channel %d: callback start", __func__, c->self);
+ debug2_f("channel %d: callback start", c->self);
c->open_confirm(ssh, c->self, 0, c->open_confirm_ctx);
- debug2("%s: channel %d: callback done", __func__, c->self);
+ debug2_f("channel %d: callback done", c->self);
}
/* Schedule the channel for cleanup/deletion. */
chan_mark_dead(ssh, c);
@@ -3257,7 +3213,7 @@ channel_input_window_adjust(int type, u_int32_t seq, struct ssh *ssh)
return 0;
if ((r = sshpkt_get_u32(ssh, &adjust)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0) {
- error("%s: adjust: %s", __func__, ssh_err(r));
+ error_fr(r, "parse adjust");
ssh_packet_disconnect(ssh, "Invalid window adjust message");
}
debug2("channel %d: rcvd adjust %u", c->self, adjust);
@@ -3279,10 +3235,10 @@ channel_input_status_confirm(int type, u_int32_t seq, struct ssh *ssh)
/* Reset keepalive timeout */
ssh_packet_set_alive_timeouts(ssh, 0);
- debug2("%s: type %d id %d", __func__, type, id);
+ debug2_f("type %d id %d", type, id);
if ((c = channel_lookup(ssh, id)) == NULL) {
- logit("%s: %d: unknown", __func__, id);
+ logit_f("%d: unknown", id);
return 0;
}
if (channel_proxy_upstream(c, type, seq, ssh))
@@ -3333,7 +3289,7 @@ channel_fwd_bind_addr(struct ssh *ssh, const char *listen_addr, int *wildcardp,
if (fwd_opts->gateway_ports)
wildcard = 1;
} else if (fwd_opts->gateway_ports || is_client) {
- if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
+ if (((ssh->compat & SSH_OLD_FORWARD_ADDR) &&
strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||
*listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
(!is_client && fwd_opts->gateway_ports == 1)) {
@@ -3407,8 +3363,8 @@ channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type,
/* Determine the bind address, cf. channel_fwd_bind_addr() comment */
addr = channel_fwd_bind_addr(ssh, fwd->listen_host, &wildcard,
is_client, fwd_opts);
- debug3("%s: type %d wildcard %d addr %s", __func__,
- type, wildcard, (addr == NULL) ? "NULL" : addr);
+ debug3_f("type %d wildcard %d addr %s", type, wildcard,
+ (addr == NULL) ? "NULL" : addr);
/*
* getaddrinfo returns a loopback address if the hostname is
@@ -3425,7 +3381,7 @@ channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type,
ssh_packet_disconnect(ssh, "getaddrinfo: fatal error: %s",
ssh_gai_strerror(r));
} else {
- error("%s: getaddrinfo(%.64s): %s", __func__, addr,
+ error_f("getaddrinfo(%.64s): %s", addr,
ssh_gai_strerror(r));
}
return 0;
@@ -3457,7 +3413,7 @@ channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type,
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
strport, sizeof(strport),
NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
- error("%s: getnameinfo failed", __func__);
+ error_f("getnameinfo failed");
continue;
}
/* Create a port to listen for the host. */
@@ -3494,7 +3450,6 @@ channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type,
}
/* Start listening for connections on the socket. */
if (listen(sock, SSH_LISTEN_BACKLOG) == -1) {
- error("listen: %.100s", strerror(errno));
error("listen [%s]:%s: %.100s", ntop, strport,
strerror(errno));
close(sock);
@@ -3522,15 +3477,14 @@ channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type,
c->host_port = fwd->connect_port;
c->listening_addr = addr == NULL ? NULL : xstrdup(addr);
if (fwd->listen_port == 0 && allocated_listen_port != NULL &&
- !(datafellows & SSH_BUG_DYNAMIC_RPORT))
+ !(ssh->compat & SSH_BUG_DYNAMIC_RPORT))
c->listening_port = *allocated_listen_port;
else
c->listening_port = fwd->listen_port;
success = 1;
}
if (success == 0)
- error("%s: cannot listen to port: %d", __func__,
- fwd->listen_port);
+ error_f("cannot listen to port: %d", fwd->listen_port);
freeaddrinfo(aitop);
return success;
}
@@ -3573,7 +3527,7 @@ channel_setup_fwd_listener_streamlocal(struct ssh *ssh, int type,
port = PORT_STREAMLOCAL;
break;
default:
- error("%s: unexpected channel type %d", __func__, type);
+ error_f("unexpected channel type %d", type);
return 0;
}
@@ -3586,7 +3540,7 @@ channel_setup_fwd_listener_streamlocal(struct ssh *ssh, int type,
return 0;
}
- debug3("%s: type %d path %s", __func__, type, fwd->listen_path);
+ debug3_f("type %d path %s", type, fwd->listen_path);
/* Start a Unix domain listener. */
omask = umask(fwd_opts->streamlocal_bind_mask);
@@ -3621,7 +3575,7 @@ channel_cancel_rport_listener_tcpip(struct ssh *ssh,
if (c == NULL || c->type != SSH_CHANNEL_RPORT_LISTENER)
continue;
if (strcmp(c->path, host) == 0 && c->listening_port == port) {
- debug2("%s: close channel %d", __func__, i);
+ debug2_f("close channel %d", i);
channel_free(ssh, c);
found = 1;
}
@@ -3643,7 +3597,7 @@ channel_cancel_rport_listener_streamlocal(struct ssh *ssh, const char *path)
if (c->path == NULL)
continue;
if (strcmp(c->path, path) == 0) {
- debug2("%s: close channel %d", __func__, i);
+ debug2_f("close channel %d", i);
channel_free(ssh, c);
found = 1;
}
@@ -3691,7 +3645,7 @@ channel_cancel_lport_listener_tcpip(struct ssh *ssh,
(c->listening_addr != NULL && addr == NULL))
continue;
if (addr == NULL || strcmp(c->listening_addr, addr) == 0) {
- debug2("%s: close channel %d", __func__, i);
+ debug2_f("close channel %d", i);
channel_free(ssh, c);
found = 1;
}
@@ -3707,7 +3661,7 @@ channel_cancel_lport_listener_streamlocal(struct ssh *ssh, const char *path)
int found = 0;
if (path == NULL) {
- error("%s: no path specified.", __func__);
+ error_f("no path specified.");
return 0;
}
@@ -3718,7 +3672,7 @@ channel_cancel_lport_listener_streamlocal(struct ssh *ssh, const char *path)
if (c->listening_addr == NULL)
continue;
if (strcmp(c->listening_addr, path) == 0) {
- debug2("%s: close channel %d", __func__, i);
+ debug2_f("close channel %d", i);
channel_free(ssh, c);
found = 1;
}
@@ -3890,8 +3844,7 @@ channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd)
(r = sshpkt_put_cstring(ssh, fwd->listen_path)) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
- fatal("%s: request streamlocal: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "request streamlocal");
} else {
if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
(r = sshpkt_put_cstring(ssh, "tcpip-forward")) != 0 ||
@@ -3901,8 +3854,7 @@ channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd)
(r = sshpkt_put_u32(ssh, fwd->listen_port)) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
- fatal("%s: request tcpip-forward: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "request tcpip-forward");
}
/* Assume that server accepts the request */
success = 1;
@@ -4010,7 +3962,7 @@ channel_request_rforward_cancel_tcpip(struct ssh *ssh,
perm = NULL;
}
if (perm == NULL) {
- debug("%s: requested forward not found", __func__);
+ debug_f("requested forward not found");
return -1;
}
if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
@@ -4019,7 +3971,7 @@ channel_request_rforward_cancel_tcpip(struct ssh *ssh,
(r = sshpkt_put_cstring(ssh, channel_rfwd_bind_host(host))) != 0 ||
(r = sshpkt_put_u32(ssh, port)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: send cancel: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send cancel");
fwd_perm_clear(perm); /* unregister */
@@ -4046,7 +3998,7 @@ channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path)
perm = NULL;
}
if (perm == NULL) {
- debug("%s: requested forward not found", __func__);
+ debug_f("requested forward not found");
return -1;
}
if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
@@ -4055,13 +4007,13 @@ channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path)
(r = sshpkt_put_u8(ssh, 0)) != 0 || /* want reply */
(r = sshpkt_put_cstring(ssh, path)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: send cancel: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send cancel");
fwd_perm_clear(perm); /* unregister */
return 0;
}
-
+
/*
* Request cancellation of remote forwarding of a connection from local side.
*/
@@ -4150,8 +4102,8 @@ channel_update_permission(struct ssh *ssh, int idx, int newport)
struct permission_set *pset = &ssh->chanctxt->local_perms;
if (idx < 0 || (u_int)idx >= pset->num_permitted_user) {
- debug("%s: index out of range: %d num_permitted_user %d",
- __func__, idx, pset->num_permitted_user);
+ debug_f("index out of range: %d num_permitted_user %d",
+ idx, pset->num_permitted_user);
return;
}
debug("%s allowed port %d for forwarding to host %s port %d",
@@ -4163,7 +4115,7 @@ channel_update_permission(struct ssh *ssh, int idx, int newport)
fwd_perm_clear(&pset->permitted_user[idx]);
else {
pset->permitted_user[idx].listen_port =
- (datafellows & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport;
+ (ssh->compat & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport;
}
}
@@ -4218,7 +4170,7 @@ connect_next(struct channel_connect *cctx)
continue;
}
if (set_nonblock(sock) == -1)
- fatal("%s: set_nonblock(%d)", __func__, sock);
+ fatal_f("set_nonblock(%d)", sock);
if (connect(sock, cctx->ai->ai_addr,
cctx->ai->ai_addrlen) == -1 && errno != EINPROGRESS) {
debug("connect_next: host %.100s ([%.100s]:%s): "
@@ -4521,8 +4473,7 @@ channel_send_window_changes(struct ssh *ssh)
(r = sshpkt_put_u32(ssh, (u_int)ws.ws_xpixel)) != 0 ||
(r = sshpkt_put_u32(ssh, (u_int)ws.ws_ypixel)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: channel %u: send window-change: %s",
- __func__, i, ssh_err(r));
+ fatal_fr(r, "channel %u; send window-change", i);
}
}
@@ -4546,10 +4497,8 @@ rdynamic_connect_prepare(struct ssh *ssh, char *ctype, char *rname)
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_u32(ssh, c->self)) != 0 ||
(r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||
- (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) {
- fatal("%s: channel %i: confirm: %s", __func__,
- c->self, ssh_err(r));
- }
+ (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0)
+ fatal_fr(r, "channel %i; confirm", c->self);
return c;
}
@@ -4557,9 +4506,28 @@ rdynamic_connect_prepare(struct ssh *ssh, char *ctype, char *rname)
static int
rdynamic_connect_finish(struct ssh *ssh, Channel *c)
{
+ struct ssh_channels *sc = ssh->chanctxt;
+ struct permission_set *pset = &sc->local_perms;
+ struct permission *perm;
struct channel_connect cctx;
+ u_int i, permit_adm = 1;
int sock;
+ if (pset->num_permitted_admin > 0) {
+ permit_adm = 0;
+ for (i = 0; i < pset->num_permitted_admin; i++) {
+ perm = &pset->permitted_admin[i];
+ if (open_match(perm, c->path, c->host_port)) {
+ permit_adm = 1;
+ break;
+ }
+ }
+ }
+ if (!permit_adm) {
+ debug_f("requested forward not permitted");
+ return -1;
+ }
+
memset(&cctx, 0, sizeof(cctx));
sock = connect_to_helper(ssh, c->path, c->host_port, SOCK_STREAM, NULL,
NULL, &cctx, NULL, NULL);
@@ -4636,8 +4604,8 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset,
if (x11_use_localhost)
set_reuseaddr(sock);
if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
- debug2("%s: bind port %d: %.100s", __func__,
- port, strerror(errno));
+ debug2_f("bind port %d: %.100s", port,
+ strerror(errno));
close(sock);
for (n = 0; n < num_socks; n++)
close(socks[n]);
@@ -4895,9 +4863,10 @@ x11_request_forwarding_with_spoofing(struct ssh *ssh, int client_session_id,
/* Extract real authentication data. */
sc->x11_saved_data = xmalloc(data_len);
for (i = 0; i < data_len; i++) {
- if (sscanf(data + 2 * i, "%2x", &value) != 1)
+ if (sscanf(data + 2 * i, "%2x", &value) != 1) {
fatal("x11_request_forwarding: bad "
"authentication data: %.100s", data);
+ }
sc->x11_saved_data[i] = value;
}
sc->x11_saved_data_len = data_len;
@@ -4919,6 +4888,6 @@ x11_request_forwarding_with_spoofing(struct ssh *ssh, int client_session_id,
(r = sshpkt_put_u32(ssh, screen_number)) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
- fatal("%s: send x11-req: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send x11-req");
free(new_data);
}
diff --git a/channels.h b/channels.h
index c8ae0d904..6bf86b003 100644
--- a/channels.h
+++ b/channels.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.h,v 1.133 2020/01/25 22:49:38 djm Exp $ */
+/* $OpenBSD: channels.h,v 1.138 2021/05/19 01:24:05 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -52,17 +52,27 @@
#define SSH_CHANNEL_DYNAMIC 13
#define SSH_CHANNEL_ZOMBIE 14 /* Almost dead. */
#define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */
-#define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux slave */
+#define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux client */
#define SSH_CHANNEL_ABANDONED 17 /* Abandoned session, eg mux */
#define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */
#define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */
-#define SSH_CHANNEL_MUX_PROXY 20 /* proxy channel for mux-slave */
+#define SSH_CHANNEL_MUX_PROXY 20 /* proxy channel for mux-client */
#define SSH_CHANNEL_RDYNAMIC_OPEN 21 /* reverse SOCKS, parsing request */
#define SSH_CHANNEL_RDYNAMIC_FINISH 22 /* reverse SOCKS, finishing connect */
#define SSH_CHANNEL_MAX_TYPE 23
#define CHANNEL_CANCEL_PORT_STATIC -1
+/* nonblocking flags for channel_new */
+#define CHANNEL_NONBLOCK_LEAVE 0 /* don't modify non-blocking state */
+#define CHANNEL_NONBLOCK_SET 1 /* set non-blocking state */
+#define CHANNEL_NONBLOCK_STDIO 2 /* set non-blocking and restore on close */
+
+/* c->restore_block mask flags */
+#define CHANNEL_RESTORE_RFD 0x01
+#define CHANNEL_RESTORE_WFD 0x02
+#define CHANNEL_RESTORE_EFD 0x04
+
/* TCP forwarding */
#define FORWARD_DENY 0
#define FORWARD_REMOTE (1)
@@ -139,6 +149,7 @@ struct Channel {
* to a matching pre-select handler.
* this way post-select handlers are not
* accidentally called if a FD gets reused */
+ int restore_block; /* fd mask to restore blocking status */
struct sshbuf *input; /* data read from socket, to be sent over
* encrypted connection */
struct sshbuf *output; /* data received over encrypted connection for
@@ -177,7 +188,7 @@ struct Channel {
channel_filter_cleanup_fn *filter_cleanup;
/* keep boundaries */
- int datagram;
+ int datagram;
/* non-blocking connect */
/* XXX make this a pointer so the structure can be opaque */
@@ -187,7 +198,7 @@ struct Channel {
mux_callback_fn *mux_rcb;
void *mux_ctx;
int mux_pause;
- int mux_downstream_id;
+ int mux_downstream_id;
};
#define CHAN_EXTENDED_IGNORE 0
@@ -223,6 +234,9 @@ struct Channel {
/* Read buffer size */
#define CHAN_RBUF (16*1024)
+/* Maximum channel input buffer size */
+#define CHAN_INPUT_MAX (16*1024*1024)
+
/* Hard limit on number of channels */
#define CHANNELS_MAX_CHANNELS (16*1024)
@@ -263,7 +277,7 @@ void channel_register_filter(struct ssh *, int, channel_infilter_fn *,
void channel_register_status_confirm(struct ssh *, int,
channel_confirm_cb *, channel_confirm_abandon_cb *, void *);
void channel_cancel_cleanup(struct ssh *, int);
-int channel_close_fd(struct ssh *, int *);
+int channel_close_fd(struct ssh *, Channel *, int *);
void channel_send_window_changes(struct ssh *);
/* mux proxy support */
@@ -286,7 +300,7 @@ int channel_input_status_confirm(int, u_int32_t, struct ssh *);
/* file descriptor handling (read/write) */
void channel_prepare_select(struct ssh *, fd_set **, fd_set **, int *,
- u_int*, time_t*);
+ u_int*, time_t*);
void channel_after_select(struct ssh *, fd_set *, fd_set *);
void channel_output_poll(struct ssh *);
@@ -310,7 +324,7 @@ Channel *channel_connect_to_port(struct ssh *, const char *, u_short,
char *, char *, int *, const char **);
Channel *channel_connect_to_path(struct ssh *, const char *, char *, char *);
Channel *channel_connect_stdio_fwd(struct ssh *, const char*,
- u_short, int, int);
+ u_short, int, int, int);
Channel *channel_connect_by_listen_address(struct ssh *, const char *,
u_short, char *, char *);
Channel *channel_connect_by_listen_path(struct ssh *, const char *,
diff --git a/cipher.c b/cipher.c
index 8195199b3..5b3a86d69 100644
--- a/cipher.c
+++ b/cipher.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cipher.c,v 1.117 2020/04/03 04:27:03 djm Exp $ */
+/* $OpenBSD: cipher.c,v 1.119 2021/04/03 06:18:40 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -91,8 +91,6 @@ static const struct sshcipher ciphers[] = {
{ "aes128-cbc", 16, 16, 0, 0, CFLAG_CBC, EVP_aes_128_cbc },
{ "aes192-cbc", 16, 24, 0, 0, CFLAG_CBC, EVP_aes_192_cbc },
{ "aes256-cbc", 16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc },
- { "rijndael-cbc@lysator.liu.se",
- 16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc },
{ "aes128-ctr", 16, 16, 0, 0, 0, EVP_aes_128_ctr },
{ "aes192-ctr", 16, 24, 0, 0, 0, EVP_aes_192_ctr },
{ "aes256-ctr", 16, 32, 0, 0, 0, EVP_aes_256_ctr },
@@ -496,10 +494,10 @@ cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, size_t len)
#endif
if (cipher_authlen(c)) {
if (!EVP_CIPHER_CTX_ctrl(cc->evp, EVP_CTRL_GCM_IV_GEN,
- len, iv))
- return SSH_ERR_LIBCRYPTO_ERROR;
+ len, iv))
+ return SSH_ERR_LIBCRYPTO_ERROR;
} else if (!EVP_CIPHER_CTX_get_iv(cc->evp, iv, len))
- return SSH_ERR_LIBCRYPTO_ERROR;
+ return SSH_ERR_LIBCRYPTO_ERROR;
#endif
return 0;
}
diff --git a/clientloop.c b/clientloop.c
index da396c72a..da14d1507 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.344 2020/04/24 02:19:40 dtucker Exp $ */
+/* $OpenBSD: clientloop.c,v 1.370 2021/08/29 23:44:07 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -115,15 +115,6 @@
/* import options */
extern Options options;
-/* Flag indicating that stdin should be redirected from /dev/null. */
-extern int stdin_null_flag;
-
-/* Flag indicating that no shell has been requested */
-extern int no_shell_flag;
-
-/* Flag indicating that ssh should daemonise after authentication is complete */
-extern int fork_after_authentication_flag;
-
/* Control socket */
extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */
@@ -162,6 +153,7 @@ static int connection_out; /* Connection to server (output). */
static int need_rekeying; /* Set to non-zero if rekeying is requested. */
static int session_closed; /* In SSH2: login session closed. */
static u_int x11_refuse_time; /* If >0, refuse x11 opens after this time. */
+static time_t server_alive_time; /* Time to do server_alive_check */
static void client_init_dispatch(struct ssh *ssh);
int session_ident = -1;
@@ -232,13 +224,13 @@ set_control_persist_exit_time(struct ssh *ssh)
} else if (channel_still_open(ssh)) {
/* some client connections are still open */
if (control_persist_exit_time > 0)
- debug2("%s: cancel scheduled exit", __func__);
+ debug2_f("cancel scheduled exit");
control_persist_exit_time = 0;
} else if (control_persist_exit_time <= 0) {
/* a client connection has recently closed */
control_persist_exit_time = monotime() +
(time_t)options.control_persist_timeout;
- debug2("%s: schedule exit in %d seconds", __func__,
+ debug2_f("schedule exit in %d seconds",
options.control_persist_timeout);
}
/* else we are already counting down to the timeout */
@@ -306,7 +298,7 @@ client_x11_get_proto(struct ssh *ssh, const char *display,
if ((r = snprintf(xdisplay, sizeof(xdisplay), "unix:%s",
display + 10)) < 0 ||
(size_t)r >= sizeof(xdisplay)) {
- error("%s: display name too long", __func__);
+ error_f("display name too long");
return -1;
}
display = xdisplay;
@@ -321,15 +313,14 @@ client_x11_get_proto(struct ssh *ssh, const char *display,
*/
mktemp_proto(xauthdir, sizeof(xauthdir));
if (mkdtemp(xauthdir) == NULL) {
- error("%s: mkdtemp: %s",
- __func__, strerror(errno));
+ error_f("mkdtemp: %s", strerror(errno));
return -1;
}
do_unlink = 1;
if ((r = snprintf(xauthfile, sizeof(xauthfile),
"%s/xauthfile", xauthdir)) < 0 ||
(size_t)r >= sizeof(xauthfile)) {
- error("%s: xauthfile path too long", __func__);
+ error_f("xauthfile path too long");
rmdir(xauthdir);
return -1;
}
@@ -355,7 +346,7 @@ client_x11_get_proto(struct ssh *ssh, const char *display,
SSH_X11_PROTO, x11_timeout_real,
_PATH_DEVNULL);
}
- debug2("%s: xauth command: %s", __func__, cmd);
+ debug2_f("xauth command: %s", cmd);
if (timeout != 0 && x11_refuse_time == 0) {
now = monotime() + 1;
@@ -444,7 +435,7 @@ client_check_window_change(struct ssh *ssh)
if (!received_window_change_signal)
return;
received_window_change_signal = 0;
- debug2("%s: changed", __func__);
+ debug2_f("changed");
channel_send_window_changes(ssh);
}
@@ -467,6 +458,13 @@ client_global_request_reply(int type, u_int32_t seq, struct ssh *ssh)
}
static void
+schedule_server_alive_check(void)
+{
+ if (options.server_alive_interval > 0)
+ server_alive_time = monotime() + options.server_alive_interval;
+}
+
+static void
server_alive_check(struct ssh *ssh)
{
int r;
@@ -479,9 +477,10 @@ server_alive_check(struct ssh *ssh)
(r = sshpkt_put_cstring(ssh, "keepalive@openssh.com")) != 0 ||
(r = sshpkt_put_u8(ssh, 1)) != 0 || /* boolean: want reply */
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: send packet: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send packet");
/* Insert an empty placeholder to maintain ordering */
client_register_global_confirm(NULL, NULL);
+ schedule_server_alive_check();
}
/*
@@ -495,7 +494,7 @@ client_wait_until_can_do_something(struct ssh *ssh,
{
struct timeval tv, *tvp;
int timeout_secs;
- time_t minwait_secs = 0, server_alive_time = 0, now = monotime();
+ time_t minwait_secs = 0, now = monotime();
int r, ret;
/* Add any selections by the channel mechanism. */
@@ -524,10 +523,8 @@ client_wait_until_can_do_something(struct ssh *ssh,
*/
timeout_secs = INT_MAX; /* we use INT_MAX to mean no timeout */
- if (options.server_alive_interval > 0) {
- timeout_secs = options.server_alive_interval;
- server_alive_time = now + options.server_alive_interval;
- }
+ if (options.server_alive_interval > 0)
+ timeout_secs = MAXIMUM(server_alive_time - now, 0);
if (options.rekey_interval > 0 && !rekeying)
timeout_secs = MINIMUM(timeout_secs,
ssh_packet_get_rekey_timeout(ssh));
@@ -557,23 +554,21 @@ client_wait_until_can_do_something(struct ssh *ssh,
*/
memset(*readsetp, 0, *nallocp);
memset(*writesetp, 0, *nallocp);
-
if (errno == EINTR)
return;
/* Note: we might still have data in the buffers. */
if ((r = sshbuf_putf(stderr_buffer,
"select: %s\r\n", strerror(errno))) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_putf");
quit_pending = 1;
- } else if (ret == 0) {
+ } else if (options.server_alive_interval > 0 && !FD_ISSET(connection_in,
+ *readsetp) && monotime() >= server_alive_time)
/*
- * Timeout. Could have been either keepalive or rekeying.
- * Keepalive we check here, rekeying is checked in clientloop.
+ * ServerAlive check is needed. We can't rely on the select
+ * timing out since traffic on the client side such as port
+ * forwards can keep waking it up.
*/
- if (server_alive_time != 0 && server_alive_time <= monotime())
- server_alive_check(ssh);
- }
-
+ server_alive_check(ssh);
}
static void
@@ -613,6 +608,7 @@ client_process_net_input(struct ssh *ssh, fd_set *readset)
* the packet subsystem.
*/
if (FD_ISSET(connection_in, readset)) {
+ schedule_server_alive_check();
/* Read as much as possible. */
len = read(connection_in, buf, sizeof(buf));
if (len == 0) {
@@ -623,8 +619,7 @@ client_process_net_input(struct ssh *ssh, fd_set *readset)
if ((r = sshbuf_putf(stderr_buffer,
"Connection to %.300s closed by remote host.\r\n",
host)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_putf");
quit_pending = 1;
return;
}
@@ -644,8 +639,7 @@ client_process_net_input(struct ssh *ssh, fd_set *readset)
if ((r = sshbuf_putf(stderr_buffer,
"Read from remote host %.300s: %.100s\r\n",
host, strerror(errno))) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_putf");
quit_pending = 1;
return;
}
@@ -693,10 +687,11 @@ client_status_confirm(struct ssh *ssh, int type, Channel *c, void *ctx)
* their stderr.
*/
if (tochan) {
+ debug3_f("channel %d: mux request: %s", c->self,
+ cr->request_type);
if ((r = sshbuf_put(c->extended, errmsg,
strlen(errmsg))) != 0)
- fatal("%s: buffer error %s", __func__,
- ssh_err(r));
+ fatal_fr(r, "sshbuf_put");
} else
error("%s", errmsg);
if (cr->action == CONFIRM_TTY) {
@@ -744,8 +739,8 @@ client_register_global_confirm(global_confirm_cb *cb, void *ctx)
last_gc = TAILQ_LAST(&global_confirms, global_confirms);
if (last_gc && last_gc->cb == cb && last_gc->ctx == ctx) {
if (++last_gc->ref_count >= INT_MAX)
- fatal("%s: last_gc->ref_count = %d",
- __func__, last_gc->ref_count);
+ fatal_f("last_gc->ref_count = %d",
+ last_gc->ref_count);
return;
}
@@ -908,7 +903,7 @@ print_escape_help(struct sshbuf *b, int escape_char, int mux_client,
if ((r = sshbuf_putf(b,
"%c?\r\nSupported escape sequences:\r\n", escape_char)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_putf");
suppress_flags =
(mux_client ? SUPPRESS_MUXCLIENT : 0) |
@@ -920,14 +915,14 @@ print_escape_help(struct sshbuf *b, int escape_char, int mux_client,
continue;
if ((r = sshbuf_putf(b, " %c%-3s - %s\r\n",
escape_char, esc_txt[i].cmd, esc_txt[i].text)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_putf");
}
if ((r = sshbuf_putf(b,
" %c%c - send the escape character by typing it twice\r\n"
"(Note that escapes are only recognized immediately after "
"newline.)\r\n", escape_char, escape_char)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_putf");
}
/*
@@ -967,8 +962,7 @@ process_escapes(struct ssh *ssh, Channel *c,
/* Terminate the connection. */
if ((r = sshbuf_putf(berr, "%c.\r\n",
efc->escape_char)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_putf");
if (c && c->ctl_chan != -1) {
chan_read_failed(ssh, c);
chan_write_failed(ssh, c);
@@ -997,16 +991,14 @@ process_escapes(struct ssh *ssh, Channel *c,
"%c%s escape not available to "
"multiplexed sessions\r\n",
efc->escape_char, b)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_putf");
continue;
}
/* Suspend the program. Inform the user */
if ((r = sshbuf_putf(berr,
"%c^Z [suspend ssh]\r\n",
efc->escape_char)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_putf");
/* Restore terminal modes and suspend. */
client_suspend_self(bin, bout, berr);
@@ -1017,17 +1009,15 @@ process_escapes(struct ssh *ssh, Channel *c,
case 'B':
if ((r = sshbuf_putf(berr,
"%cB\r\n", efc->escape_char)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_putf");
channel_request_start(ssh, c->self, "break", 0);
if ((r = sshpkt_put_u32(ssh, 1000)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: send packet: %s", __func__,
- ssh_err(r));
+ fatal_fr(r, "send packet");
continue;
case 'R':
- if (datafellows & SSH_BUG_NOREKEY)
+ if (ssh->compat & SSH_BUG_NOREKEY)
logit("Server does not "
"support re-keying");
else
@@ -1043,8 +1033,7 @@ process_escapes(struct ssh *ssh, Channel *c,
if ((r = sshbuf_putf(berr,
"%c%c [Logging to syslog]\r\n",
efc->escape_char, ch)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_putf");
continue;
}
if (ch == 'V' && options.log_level >
@@ -1057,8 +1046,7 @@ process_escapes(struct ssh *ssh, Channel *c,
"%c%c [LogLevel %s]\r\n",
efc->escape_char, ch,
log_level_name(options.log_level))) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_putf");
continue;
case '&':
@@ -1076,11 +1064,9 @@ process_escapes(struct ssh *ssh, Channel *c,
/* Stop listening for new connections. */
channel_stop_listening(ssh);
- if ((r = sshbuf_putf(berr,
- "%c& [backgrounded]\n", efc->escape_char))
- != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ if ((r = sshbuf_putf(berr, "%c& "
+ "[backgrounded]\n", efc->escape_char)) != 0)
+ fatal_fr(r, "sshbuf_putf");
/* Fork into background. */
pid = fork();
@@ -1095,8 +1081,7 @@ process_escapes(struct ssh *ssh, Channel *c,
/* The child continues serving connections. */
/* fake EOF on stdin */
if ((r = sshbuf_put_u8(bin, 4)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_put_u8");
return -1;
case '?':
print_escape_help(berr, efc->escape_char,
@@ -1107,12 +1092,10 @@ process_escapes(struct ssh *ssh, Channel *c,
case '#':
if ((r = sshbuf_putf(berr, "%c#\r\n",
efc->escape_char)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_putf");
s = channel_open_message(ssh);
if ((r = sshbuf_put(berr, s, strlen(s))) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_put");
free(s);
continue;
@@ -1126,8 +1109,7 @@ process_escapes(struct ssh *ssh, Channel *c,
if (ch != efc->escape_char) {
if ((r = sshbuf_put_u8(bin,
efc->escape_char)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_put_u8");
bytes++;
}
/* Escaped characters fall through here */
@@ -1154,7 +1136,7 @@ process_escapes(struct ssh *ssh, Channel *c,
*/
last_was_cr = (ch == '\r' || ch == '\n');
if ((r = sshbuf_put_u8(bin, ch)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_put_u8");
bytes++;
}
return bytes;
@@ -1232,7 +1214,6 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
int r, max_fd = 0, max_fd2 = 0, len;
u_int64_t ibytes, obytes;
u_int nalloc = 0;
- char buf[100];
debug("Entering interactive session.");
@@ -1241,30 +1222,30 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
debug("pledge: id");
if (pledge("stdio rpath wpath cpath unix inet dns recvfd sendfd proc exec id tty",
NULL) == -1)
- fatal("%s pledge(): %s", __func__, strerror(errno));
+ fatal_f("pledge(): %s", strerror(errno));
} else if (options.forward_x11 || options.permit_local_command) {
debug("pledge: exec");
if (pledge("stdio rpath wpath cpath unix inet dns proc exec tty",
NULL) == -1)
- fatal("%s pledge(): %s", __func__, strerror(errno));
+ fatal_f("pledge(): %s", strerror(errno));
} else if (options.update_hostkeys) {
debug("pledge: filesystem full");
if (pledge("stdio rpath wpath cpath unix inet dns proc tty",
NULL) == -1)
- fatal("%s pledge(): %s", __func__, strerror(errno));
+ fatal_f("pledge(): %s", strerror(errno));
} else if (!option_clear_or_none(options.proxy_command) ||
- fork_after_authentication_flag) {
+ options.fork_after_authentication) {
debug("pledge: proc");
if (pledge("stdio cpath unix inet dns proc tty", NULL) == -1)
- fatal("%s pledge(): %s", __func__, strerror(errno));
+ fatal_f("pledge(): %s", strerror(errno));
} else {
debug("pledge: network");
if (pledge("stdio unix inet dns proc tty", NULL) == -1)
- fatal("%s pledge(): %s", __func__, strerror(errno));
+ fatal_f("pledge(): %s", strerror(errno));
}
start_time = monotime_double();
@@ -1280,7 +1261,7 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
/* Initialize buffer. */
if ((stderr_buffer = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
client_init_dispatch(ssh);
@@ -1314,6 +1295,8 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
client_channel_closed, 0);
}
+ schedule_server_alive_check();
+
/* Main loop of the client for the interactive session mode. */
while (!quit_pending) {
@@ -1329,8 +1312,7 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
/* manual rekey request */
debug("need rekeying");
if ((r = kex_start_rekex(ssh)) != 0)
- fatal("%s: kex_start_rekex: %s", __func__,
- ssh_err(r));
+ fatal_fr(r, "kex_start_rekex");
need_rekeying = 0;
} else {
/*
@@ -1370,6 +1352,10 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
if (quit_pending)
break;
+ /* A timeout may have triggered rekeying */
+ if ((r = ssh_packet_check_rekey(ssh)) != 0)
+ fatal_fr(r, "cannot start rekeying");
+
/*
* Send as much buffered packet data as possible to the
* sender.
@@ -1407,34 +1393,27 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
(r = sshpkt_put_cstring(ssh, "")) != 0 || /* language tag */
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
- fatal("%s: send disconnect: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send disconnect");
channel_free_all(ssh);
if (have_pty)
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
- /* restore blocking io */
- if (!isatty(fileno(stdin)))
- unset_nonblock(fileno(stdin));
- if (!isatty(fileno(stdout)))
- unset_nonblock(fileno(stdout));
- if (!isatty(fileno(stderr)))
- unset_nonblock(fileno(stderr));
-
/*
* If there was no shell or command requested, there will be no remote
* exit status to be returned. In that case, clear error code if the
* connection was deliberately terminated at this end.
*/
- if (no_shell_flag && received_signal == SIGTERM) {
+ if (options.session_type == SESSION_TYPE_NONE &&
+ received_signal == SIGTERM) {
received_signal = 0;
exit_status = 0;
}
if (received_signal) {
verbose("Killed by signal %d.", (int) received_signal);
- cleanup_exit(0);
+ cleanup_exit(255);
}
/*
@@ -1444,7 +1423,7 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {
if ((r = sshbuf_putf(stderr_buffer,
"Connection to %.64s closed.\r\n", host)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_putf");
}
/* Output any buffered data for stderr. */
@@ -1455,11 +1434,10 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
if (len < 0 || (u_int)len != sshbuf_len(stderr_buffer))
error("Write failed flushing stderr buffer.");
else if ((r = sshbuf_consume(stderr_buffer, len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_consume");
}
/* Clear and free any buffers. */
- explicit_bzero(buf, sizeof(buf));
sshbuf_free(stderr_buffer);
/* Report bytes transferred, and transfer rates. */
@@ -1493,15 +1471,15 @@ client_request_forwarded_tcpip(struct ssh *ssh, const char *request_type,
(r = sshpkt_get_cstring(ssh, &originator_address, NULL)) != 0 ||
(r = sshpkt_get_u32(ssh, &originator_port)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0)
- fatal("%s: parse packet: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse packet");
- debug("%s: listen %s port %d, originator %s port %d", __func__,
+ debug_f("listen %s port %d, originator %s port %d",
listen_address, listen_port, originator_address, originator_port);
if (listen_port > 0xffff)
- error("%s: invalid listen port", __func__);
+ error_f("invalid listen port");
else if (originator_port > 0xffff)
- error("%s: invalid originator port", __func__);
+ error_f("invalid originator port");
else {
c = channel_connect_by_listen_address(ssh,
listen_address, listen_port, "forwarded-tcpip",
@@ -1510,7 +1488,7 @@ client_request_forwarded_tcpip(struct ssh *ssh, const char *request_type,
if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) {
if ((b = sshbuf_new()) == NULL) {
- error("%s: alloc reply", __func__);
+ error_f("alloc reply");
goto out;
}
/* reconstruct and send to muxclient */
@@ -1525,8 +1503,7 @@ client_request_forwarded_tcpip(struct ssh *ssh, const char *request_type,
(r = sshbuf_put_cstring(b, originator_address)) != 0 ||
(r = sshbuf_put_u32(b, originator_port)) != 0 ||
(r = sshbuf_put_stringb(c->output, b)) != 0) {
- error("%s: compose for muxclient %s", __func__,
- ssh_err(r));
+ error_fr(r, "compose for muxclient");
goto out;
}
}
@@ -1550,9 +1527,9 @@ client_request_forwarded_streamlocal(struct ssh *ssh,
if ((r = sshpkt_get_cstring(ssh, &listen_path, NULL)) != 0 ||
(r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* reserved */
(r = sshpkt_get_end(ssh)) != 0)
- fatal("%s: parse packet: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse packet");
- debug("%s: request: %s", __func__, listen_path);
+ debug_f("request: %s", listen_path);
c = channel_connect_by_listen_path(ssh, listen_path,
"forwarded-streamlocal@openssh.com", "forwarded-streamlocal");
@@ -1582,7 +1559,7 @@ client_request_x11(struct ssh *ssh, const char *request_type, int rchan)
if ((r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 ||
(r = sshpkt_get_u32(ssh, &originator_port)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0)
- fatal("%s: parse packet: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse packet");
/* XXX check permission */
/* XXX range check originator port? */
debug("client_request_x11: request from %s %u", originator,
@@ -1617,8 +1594,7 @@ client_request_agent(struct ssh *ssh, const char *request_type, int rchan)
}
if (r != 0) {
if (r != SSH_ERR_AGENT_NOT_PRESENT)
- debug("%s: ssh_get_authentication_socket: %s",
- __func__, ssh_err(r));
+ debug_fr(r, "ssh_get_authentication_socket");
return NULL;
}
c = channel_new(ssh, "authentication agent connection",
@@ -1779,16 +1755,15 @@ client_input_channel_req(int type, u_int32_t seq, struct ssh *ssh)
exit_status = exitval;
} else {
/* Probably for a mux channel that has already closed */
- debug("%s: no sink for exit-status on channel %d",
- __func__, id);
+ debug_f("no sink for exit-status on channel %d",
+ id);
}
if ((r = sshpkt_get_end(ssh)) != 0)
goto out;
}
if (reply && c != NULL && !(c->flags & CHAN_CLOSE_SENT)) {
if (!c->have_remote_id)
- fatal("%s: channel %d: no remote_id",
- __func__, c->self);
+ fatal_f("channel %d: no remote_id", c->self);
if ((r = sshpkt_start(ssh, success ?
SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
@@ -1808,12 +1783,13 @@ struct hostkeys_update_ctx {
/*
* Keys received from the server and a flag for each indicating
* whether they already exist in known_hosts.
- * keys_seen is filled in by hostkeys_find() and later (for new
+ * keys_match is filled in by hostkeys_find() and later (for new
* keys) by client_global_hostkeys_private_confirm().
*/
struct sshkey **keys;
- int *keys_seen;
- size_t nkeys, nnew;
+ u_int *keys_match; /* mask of HKF_MATCH_* from hostfile.h */
+ int *keys_verified; /* flag for new keys verified by server */
+ size_t nkeys, nnew, nincomplete; /* total, new keys, incomplete match */
/*
* Keys that are in known_hosts, but were not present in the update
@@ -1822,6 +1798,12 @@ struct hostkeys_update_ctx {
*/
struct sshkey **old_keys;
size_t nold;
+
+ /* Various special cases. */
+ int complex_hostspec; /* wildcard or manual pattern-list host name */
+ int ca_available; /* saw CA key for this host */
+ int old_key_seen; /* saw old key with other name/addr */
+ int other_name_seen; /* saw key with other name/addr */
};
static void
@@ -1834,7 +1816,8 @@ hostkeys_update_ctx_free(struct hostkeys_update_ctx *ctx)
for (i = 0; i < ctx->nkeys; i++)
sshkey_free(ctx->keys[i]);
free(ctx->keys);
- free(ctx->keys_seen);
+ free(ctx->keys_match);
+ free(ctx->keys_verified);
for (i = 0; i < ctx->nold; i++)
sshkey_free(ctx->old_keys[i]);
free(ctx->old_keys);
@@ -1843,6 +1826,30 @@ hostkeys_update_ctx_free(struct hostkeys_update_ctx *ctx)
free(ctx);
}
+/*
+ * Returns non-zero if a known_hosts hostname list is not of a form that
+ * can be handled by UpdateHostkeys. These include wildcard hostnames and
+ * hostnames lists that do not follow the form host[,ip].
+ */
+static int
+hostspec_is_complex(const char *hosts)
+{
+ char *cp;
+
+ /* wildcard */
+ if (strchr(hosts, '*') != NULL || strchr(hosts, '?') != NULL)
+ return 1;
+ /* single host/ip = ok */
+ if ((cp = strchr(hosts, ',')) == NULL)
+ return 0;
+ /* more than two entries on the line */
+ if (strchr(cp + 1, ',') != NULL)
+ return 1;
+ /* XXX maybe parse cp+1 and ensure it is an IP? */
+ return 0;
+}
+
+/* callback to search for ctx->keys in known_hosts */
static int
hostkeys_find(struct hostkey_foreach_line *l, void *_ctx)
{
@@ -1850,25 +1857,73 @@ hostkeys_find(struct hostkey_foreach_line *l, void *_ctx)
size_t i;
struct sshkey **tmp;
- if (l->status != HKF_STATUS_MATCHED || l->key == NULL)
+ if (l->key == NULL)
+ return 0;
+ if (l->status != HKF_STATUS_MATCHED) {
+ /* Record if one of the keys appears on a non-matching line */
+ for (i = 0; i < ctx->nkeys; i++) {
+ if (sshkey_equal(l->key, ctx->keys[i])) {
+ ctx->other_name_seen = 1;
+ debug3_f("found %s key under different "
+ "name/addr at %s:%ld",
+ sshkey_ssh_name(ctx->keys[i]),
+ l->path, l->linenum);
+ return 0;
+ }
+ }
+ return 0;
+ }
+ /* Don't proceed if revocation or CA markers are present */
+ /* XXX relax this */
+ if (l->marker != MRK_NONE) {
+ debug3_f("hostkeys file %s:%ld has CA/revocation marker",
+ l->path, l->linenum);
+ ctx->complex_hostspec = 1;
+ return 0;
+ }
+
+ /* If CheckHostIP is enabled, then check for mismatched hostname/addr */
+ if (ctx->ip_str != NULL && strchr(l->hosts, ',') != NULL) {
+ if ((l->match & HKF_MATCH_HOST) == 0) {
+ /* Record if address matched a different hostname. */
+ ctx->other_name_seen = 1;
+ debug3_f("found address %s against different hostname "
+ "at %s:%ld", ctx->ip_str, l->path, l->linenum);
+ return 0;
+ } else if ((l->match & HKF_MATCH_IP) == 0) {
+ /* Record if hostname matched a different address. */
+ ctx->other_name_seen = 1;
+ debug3_f("found hostname %s against different address "
+ "at %s:%ld", ctx->host_str, l->path, l->linenum);
+ }
+ }
+
+ /*
+ * UpdateHostkeys is skipped for wildcard host names and hostnames
+ * that contain more than two entries (ssh never writes these).
+ */
+ if (hostspec_is_complex(l->hosts)) {
+ debug3_f("hostkeys file %s:%ld complex host specification",
+ l->path, l->linenum);
+ ctx->complex_hostspec = 1;
return 0;
+ }
/* Mark off keys we've already seen for this host */
for (i = 0; i < ctx->nkeys; i++) {
- if (sshkey_equal(l->key, ctx->keys[i])) {
- debug3("%s: found %s key at %s:%ld", __func__,
- sshkey_ssh_name(ctx->keys[i]), l->path, l->linenum);
- ctx->keys_seen[i] = 1;
- return 0;
- }
+ if (!sshkey_equal(l->key, ctx->keys[i]))
+ continue;
+ debug3_f("found %s key at %s:%ld",
+ sshkey_ssh_name(ctx->keys[i]), l->path, l->linenum);
+ ctx->keys_match[i] |= l->match;
+ return 0;
}
/* This line contained a key that not offered by the server */
- debug3("%s: deprecated %s key at %s:%ld", __func__,
- sshkey_ssh_name(l->key), l->path, l->linenum);
+ debug3_f("deprecated %s key at %s:%ld", sshkey_ssh_name(l->key),
+ l->path, l->linenum);
if ((tmp = recallocarray(ctx->old_keys, ctx->nold, ctx->nold + 1,
sizeof(*ctx->old_keys))) == NULL)
- fatal("%s: recallocarray failed nold = %zu",
- __func__, ctx->nold);
+ fatal_f("recallocarray failed nold = %zu", ctx->nold);
ctx->old_keys = tmp;
ctx->old_keys[ctx->nold++] = l->key;
l->key = NULL;
@@ -1876,6 +1931,63 @@ hostkeys_find(struct hostkey_foreach_line *l, void *_ctx)
return 0;
}
+/* callback to search for ctx->old_keys in known_hosts under other names */
+static int
+hostkeys_check_old(struct hostkey_foreach_line *l, void *_ctx)
+{
+ struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx;
+ size_t i;
+ int hashed;
+
+ /* only care about lines that *don't* match the active host spec */
+ if (l->status == HKF_STATUS_MATCHED || l->key == NULL)
+ return 0;
+
+ hashed = l->match & (HKF_MATCH_HOST_HASHED|HKF_MATCH_IP_HASHED);
+ for (i = 0; i < ctx->nold; i++) {
+ if (!sshkey_equal(l->key, ctx->old_keys[i]))
+ continue;
+ debug3_f("found deprecated %s key at %s:%ld as %s",
+ sshkey_ssh_name(ctx->old_keys[i]), l->path, l->linenum,
+ hashed ? "[HASHED]" : l->hosts);
+ ctx->old_key_seen = 1;
+ break;
+ }
+ return 0;
+}
+
+/*
+ * Check known_hosts files for deprecated keys under other names. Returns 0
+ * on success or -1 on failure. Updates ctx->old_key_seen if deprecated keys
+ * exist under names other than the active hostname/IP.
+ */
+static int
+check_old_keys_othernames(struct hostkeys_update_ctx *ctx)
+{
+ size_t i;
+ int r;
+
+ debug2_f("checking for %zu deprecated keys", ctx->nold);
+ for (i = 0; i < options.num_user_hostfiles; i++) {
+ debug3_f("searching %s for %s / %s",
+ options.user_hostfiles[i], ctx->host_str,
+ ctx->ip_str ? ctx->ip_str : "(none)");
+ if ((r = hostkeys_foreach(options.user_hostfiles[i],
+ hostkeys_check_old, ctx, ctx->host_str, ctx->ip_str,
+ HKF_WANT_PARSE_KEY, 0)) != 0) {
+ if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT) {
+ debug_f("hostkeys file %s does not exist",
+ options.user_hostfiles[i]);
+ continue;
+ }
+ error_fr(r, "hostkeys_foreach failed for %s",
+ options.user_hostfiles[i]);
+ return -1;
+ }
+ }
+ return 0;
+}
+
static void
hostkey_change_preamble(LogLevel loglevel)
{
@@ -1895,11 +2007,11 @@ update_known_hosts(struct hostkeys_update_ctx *ctx)
struct stat sb;
for (i = 0; i < ctx->nkeys; i++) {
- if (ctx->keys_seen[i] != 2)
+ if (!ctx->keys_verified[i])
continue;
if ((fp = sshkey_fingerprint(ctx->keys[i],
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
- fatal("%s: sshkey_fingerprint failed", __func__);
+ fatal_f("sshkey_fingerprint failed");
if (first && asking)
hostkey_change_preamble(loglevel);
do_log2(loglevel, "Learned new hostkey: %s %s",
@@ -1910,7 +2022,7 @@ update_known_hosts(struct hostkeys_update_ctx *ctx)
for (i = 0; i < ctx->nold; i++) {
if ((fp = sshkey_fingerprint(ctx->old_keys[i],
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
- fatal("%s: sshkey_fingerprint failed", __func__);
+ fatal_f("sshkey_fingerprint failed");
if (first && asking)
hostkey_change_preamble(loglevel);
do_log2(loglevel, "Deprecating obsolete hostkey: %s %s",
@@ -1959,11 +2071,12 @@ update_known_hosts(struct hostkeys_update_ctx *ctx)
*/
if (stat(options.user_hostfiles[i], &sb) != 0) {
if (errno == ENOENT) {
- debug("%s: known hosts file %s does not exist",
- __func__, strerror(errno));
+ debug_f("known hosts file %s does not "
+ "exist", options.user_hostfiles[i]);
} else {
- error("%s: known hosts file %s inaccessible",
- __func__, strerror(errno));
+ error_f("known hosts file %s "
+ "inaccessible: %s",
+ options.user_hostfiles[i], strerror(errno));
}
continue;
}
@@ -1972,8 +2085,8 @@ update_known_hosts(struct hostkeys_update_ctx *ctx)
i == 0 ? ctx->keys : NULL, i == 0 ? ctx->nkeys : 0,
options.hash_known_hosts, 0,
options.fingerprint_hash)) != 0) {
- error("%s: hostfile_replace_entries failed for %s: %s",
- __func__, options.user_hostfiles[i], ssh_err(r));
+ error_fr(r, "hostfile_replace_entries failed for %s",
+ options.user_hostfiles[i]);
}
}
}
@@ -1990,7 +2103,7 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type,
size_t siglen;
if (ctx->nnew == 0)
- fatal("%s: ctx->nnew == 0", __func__); /* sanity */
+ fatal_f("ctx->nnew == 0"); /* sanity */
if (type != SSH2_MSG_REQUEST_SUCCESS) {
error("Server failed to confirm ownership of "
"private host keys");
@@ -2001,31 +2114,26 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type,
sshkey_type_from_name(ssh->kex->hostkey_alg));
if ((signdata = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
- /* Don't want to accidentally accept an unbound signature */
- if (ssh->kex->session_id_len == 0)
- fatal("%s: ssh->kex->session_id_len == 0", __func__);
+ fatal_f("sshbuf_new failed");
/*
* Expect a signature for each of the ctx->nnew private keys we
* haven't seen before. They will be in the same order as the
- * ctx->keys where the corresponding ctx->keys_seen[i] == 0.
+ * ctx->keys where the corresponding ctx->keys_match[i] == 0.
*/
for (ndone = i = 0; i < ctx->nkeys; i++) {
- if (ctx->keys_seen[i])
+ if (ctx->keys_match[i])
continue;
/* Prepare data to be signed: session ID, unique string, key */
sshbuf_reset(signdata);
if ( (r = sshbuf_put_cstring(signdata,
"hostkeys-prove-00@openssh.com")) != 0 ||
- (r = sshbuf_put_string(signdata, ssh->kex->session_id,
- ssh->kex->session_id_len)) != 0 ||
+ (r = sshbuf_put_stringb(signdata,
+ ssh->kex->session_id)) != 0 ||
(r = sshkey_puts(ctx->keys[i], signdata)) != 0)
- fatal("%s: failed to prepare signature: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "compose signdata");
/* Extract and verify signature */
if ((r = sshpkt_get_string_direct(ssh, &sig, &siglen)) != 0) {
- error("%s: couldn't parse message: %s",
- __func__, ssh_err(r));
+ error_fr(r, "parse sig");
goto out;
}
/*
@@ -2034,23 +2142,26 @@ client_global_hostkeys_private_confirm(struct ssh *ssh, int type,
*/
use_kexsigtype = kexsigtype == KEY_RSA &&
sshkey_type_plain(ctx->keys[i]->type) == KEY_RSA;
+ debug3_f("verify %s key %zu using %s sigalg",
+ sshkey_type(ctx->keys[i]), i,
+ use_kexsigtype ? ssh->kex->hostkey_alg : "default");
if ((r = sshkey_verify(ctx->keys[i], sig, siglen,
sshbuf_ptr(signdata), sshbuf_len(signdata),
use_kexsigtype ? ssh->kex->hostkey_alg : NULL, 0,
NULL)) != 0) {
- error("%s: server gave bad signature for %s key %zu",
- __func__, sshkey_type(ctx->keys[i]), i);
+ error_fr(r, "server gave bad signature for %s key %zu",
+ sshkey_type(ctx->keys[i]), i);
goto out;
}
/* Key is good. Mark it as 'seen' */
- ctx->keys_seen[i] = 2;
+ ctx->keys_verified[i] = 1;
ndone++;
}
+ /* Shouldn't happen */
if (ndone != ctx->nnew)
- fatal("%s: ndone != ctx->nnew (%zu / %zu)", __func__,
- ndone, ctx->nnew); /* Shouldn't happen */
+ fatal_f("ndone != ctx->nnew (%zu / %zu)", ndone, ctx->nnew);
if ((r = sshpkt_get_end(ssh)) != 0) {
- error("%s: protocol error", __func__);
+ error_f("protocol error");
goto out;
}
@@ -2096,9 +2207,10 @@ client_input_hostkeys(struct ssh *ssh)
static int hostkeys_seen = 0; /* XXX use struct ssh */
extern struct sockaddr_storage hostaddr; /* XXX from ssh.c */
struct hostkeys_update_ctx *ctx = NULL;
+ u_int want;
if (hostkeys_seen)
- fatal("%s: server already sent hostkeys", __func__);
+ fatal_f("server already sent hostkeys");
if (options.update_hostkeys == SSH_UPDATE_HOSTKEYS_ASK &&
options.batch_mode)
return 1; /* won't ask in batchmode, so don't even try */
@@ -2110,59 +2222,59 @@ client_input_hostkeys(struct ssh *ssh)
sshkey_free(key);
key = NULL;
if ((r = sshpkt_get_string_direct(ssh, &blob, &len)) != 0) {
- error("%s: couldn't parse message: %s",
- __func__, ssh_err(r));
+ error_fr(r, "parse key");
goto out;
}
if ((r = sshkey_from_blob(blob, len, &key)) != 0) {
- do_log2(r == SSH_ERR_KEY_TYPE_UNKNOWN ?
+ do_log2_fr(r, r == SSH_ERR_KEY_TYPE_UNKNOWN ?
SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_ERROR,
- "%s: parse key: %s", __func__, ssh_err(r));
+ "convert key");
continue;
}
fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT);
- debug3("%s: received %s key %s", __func__,
- sshkey_type(key), fp);
+ debug3_f("received %s key %s", sshkey_type(key), fp);
free(fp);
if (!key_accepted_by_hostkeyalgs(key)) {
- debug3("%s: %s key not permitted by HostkeyAlgorithms",
- __func__, sshkey_ssh_name(key));
+ debug3_f("%s key not permitted by "
+ "HostkeyAlgorithms", sshkey_ssh_name(key));
continue;
}
/* Skip certs */
if (sshkey_is_cert(key)) {
- debug3("%s: %s key is a certificate; skipping",
- __func__, sshkey_ssh_name(key));
+ debug3_f("%s key is a certificate; skipping",
+ sshkey_ssh_name(key));
continue;
}
/* Ensure keys are unique */
for (i = 0; i < ctx->nkeys; i++) {
if (sshkey_equal(key, ctx->keys[i])) {
- error("%s: received duplicated %s host key",
- __func__, sshkey_ssh_name(key));
+ error_f("received duplicated %s host key",
+ sshkey_ssh_name(key));
goto out;
}
}
/* Key is good, record it */
if ((tmp = recallocarray(ctx->keys, ctx->nkeys, ctx->nkeys + 1,
sizeof(*ctx->keys))) == NULL)
- fatal("%s: recallocarray failed nkeys = %zu",
- __func__, ctx->nkeys);
+ fatal_f("recallocarray failed nkeys = %zu",
+ ctx->nkeys);
ctx->keys = tmp;
ctx->keys[ctx->nkeys++] = key;
key = NULL;
}
if (ctx->nkeys == 0) {
- debug("%s: server sent no hostkeys", __func__);
+ debug_f("server sent no hostkeys");
goto out;
}
- if ((ctx->keys_seen = calloc(ctx->nkeys,
- sizeof(*ctx->keys_seen))) == NULL)
- fatal("%s: calloc failed", __func__);
+ if ((ctx->keys_match = calloc(ctx->nkeys,
+ sizeof(*ctx->keys_match))) == NULL ||
+ (ctx->keys_verified = calloc(ctx->nkeys,
+ sizeof(*ctx->keys_verified))) == NULL)
+ fatal_f("calloc failed");
get_hostfile_hostname_ipaddr(host,
options.check_host_ip ? (struct sockaddr *)&hostaddr : NULL,
@@ -2171,68 +2283,107 @@ client_input_hostkeys(struct ssh *ssh)
/* Find which keys we already know about. */
for (i = 0; i < options.num_user_hostfiles; i++) {
- debug("%s: searching %s for %s / %s", __func__,
+ debug_f("searching %s for %s / %s",
options.user_hostfiles[i], ctx->host_str,
ctx->ip_str ? ctx->ip_str : "(none)");
if ((r = hostkeys_foreach(options.user_hostfiles[i],
hostkeys_find, ctx, ctx->host_str, ctx->ip_str,
- HKF_WANT_PARSE_KEY|HKF_WANT_MATCH)) != 0) {
+ HKF_WANT_PARSE_KEY, 0)) != 0) {
if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT) {
- debug("%s: hostkeys file %s does not exist",
- __func__, options.user_hostfiles[i]);
+ debug_f("hostkeys file %s does not exist",
+ options.user_hostfiles[i]);
continue;
}
- error("%s: hostkeys_foreach failed for %s: %s",
- __func__, options.user_hostfiles[i], ssh_err(r));
+ error_fr(r, "hostkeys_foreach failed for %s",
+ options.user_hostfiles[i]);
goto out;
}
}
/* Figure out if we have any new keys to add */
- ctx->nnew = 0;
+ ctx->nnew = ctx->nincomplete = 0;
+ want = HKF_MATCH_HOST | ( options.check_host_ip ? HKF_MATCH_IP : 0);
for (i = 0; i < ctx->nkeys; i++) {
- if (!ctx->keys_seen[i])
+ if (ctx->keys_match[i] == 0)
ctx->nnew++;
+ if ((ctx->keys_match[i] & want) != want)
+ ctx->nincomplete++;
}
- debug3("%s: %zu keys from server: %zu new, %zu retained. %zu to remove",
- __func__, ctx->nkeys, ctx->nnew, ctx->nkeys - ctx->nnew, ctx->nold);
+ debug3_f("%zu server keys: %zu new, %zu retained, "
+ "%zu incomplete match. %zu to remove", ctx->nkeys, ctx->nnew,
+ ctx->nkeys - ctx->nnew - ctx->nincomplete,
+ ctx->nincomplete, ctx->nold);
- if (ctx->nnew == 0 && ctx->nold != 0) {
- /* We have some keys to remove. Just do it. */
- update_known_hosts(ctx);
- } else if (ctx->nnew != 0) {
+ if (ctx->nnew == 0 && ctx->nold == 0) {
+ debug_f("no new or deprecated keys from server");
+ goto out;
+ }
+
+ /* Various reasons why we cannot proceed with the update */
+ if (ctx->complex_hostspec) {
+ debug_f("CA/revocation marker, manual host list or wildcard "
+ "host pattern found, skipping UserKnownHostsFile update");
+ goto out;
+ }
+ if (ctx->other_name_seen) {
+ debug_f("host key found matching a different name/address, "
+ "skipping UserKnownHostsFile update");
+ goto out;
+ }
+ /*
+ * If removing keys, check whether they appear under different
+ * names/addresses and refuse to proceed if they do. This avoids
+ * cases such as hosts with multiple names becoming inconsistent
+ * with regards to CheckHostIP entries.
+ * XXX UpdateHostkeys=force to override this (and other) checks?
+ */
+ if (ctx->nold != 0) {
+ if (check_old_keys_othernames(ctx) != 0)
+ goto out; /* error already logged */
+ if (ctx->old_key_seen) {
+ debug_f("key(s) for %s%s%s exist under other names; "
+ "skipping UserKnownHostsFile update",
+ ctx->host_str, ctx->ip_str == NULL ? "" : ",",
+ ctx->ip_str == NULL ? "" : ctx->ip_str);
+ goto out;
+ }
+ }
+
+ if (ctx->nnew == 0) {
/*
- * We have received hitherto-unseen keys from the server.
- * Ask the server to confirm ownership of the private halves.
+ * We have some keys to remove or fix matching for.
+ * We can proceed to do this without requiring a fresh proof
+ * from the server.
*/
- debug3("%s: asking server to prove ownership for %zu keys",
- __func__, ctx->nnew);
- if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
- (r = sshpkt_put_cstring(ssh,
- "hostkeys-prove-00@openssh.com")) != 0 ||
- (r = sshpkt_put_u8(ssh, 1)) != 0) /* bool: want reply */
- fatal("%s: cannot prepare packet: %s",
- __func__, ssh_err(r));
- if ((buf = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
- for (i = 0; i < ctx->nkeys; i++) {
- if (ctx->keys_seen[i])
- continue;
- sshbuf_reset(buf);
- if ((r = sshkey_putb(ctx->keys[i], buf)) != 0)
- fatal("%s: sshkey_putb: %s",
- __func__, ssh_err(r));
- if ((r = sshpkt_put_stringb(ssh, buf)) != 0)
- fatal("%s: sshpkt_put_string: %s",
- __func__, ssh_err(r));
- }
- if ((r = sshpkt_send(ssh)) != 0)
- fatal("%s: sshpkt_send: %s", __func__, ssh_err(r));
- client_register_global_confirm(
- client_global_hostkeys_private_confirm, ctx);
- ctx = NULL; /* will be freed in callback */
+ update_known_hosts(ctx);
+ goto out;
+ }
+ /*
+ * We have received previously-unseen keys from the server.
+ * Ask the server to confirm ownership of the private halves.
+ */
+ debug3_f("asking server to prove ownership for %zu keys", ctx->nnew);
+ if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
+ (r = sshpkt_put_cstring(ssh,
+ "hostkeys-prove-00@openssh.com")) != 0 ||
+ (r = sshpkt_put_u8(ssh, 1)) != 0) /* bool: want reply */
+ fatal_fr(r, "prepare hostkeys-prove");
+ if ((buf = sshbuf_new()) == NULL)
+ fatal_f("sshbuf_new");
+ for (i = 0; i < ctx->nkeys; i++) {
+ if (ctx->keys_match[i])
+ continue;
+ sshbuf_reset(buf);
+ if ((r = sshkey_putb(ctx->keys[i], buf)) != 0 ||
+ (r = sshpkt_put_stringb(ssh, buf)) != 0)
+ fatal_fr(r, "assemble hostkeys-prove");
}
+ if ((r = sshpkt_send(ssh)) != 0)
+ fatal_fr(r, "send hostkeys-prove");
+ client_register_global_confirm(
+ client_global_hostkeys_private_confirm, ctx);
+ ctx = NULL; /* will be freed in callback */
/* Success */
out:
@@ -2273,6 +2424,19 @@ client_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
return r;
}
+static void
+client_send_env(struct ssh *ssh, int id, const char *name, const char *val)
+{
+ int r;
+
+ debug("channel %d: setting env %s = \"%s\"", id, name, val);
+ channel_request_start(ssh, id, "env", 0);
+ if ((r = sshpkt_put_cstring(ssh, name)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, val)) != 0 ||
+ (r = sshpkt_send(ssh)) != 0)
+ fatal_fr(r, "send setenv");
+}
+
void
client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem,
const char *term, struct termios *tiop, int in_fd, struct sshbuf *cmd,
@@ -2282,10 +2446,10 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem,
char *name, *val;
Channel *c = NULL;
- debug2("%s: id %d", __func__, id);
+ debug2_f("id %d", id);
if ((c = channel_lookup(ssh, id)) == NULL)
- fatal("%s: channel %d: unknown channel", __func__, id);
+ fatal_f("channel %d: unknown channel", id);
ssh_packet_set_interactive(ssh, want_tty,
options.ip_qos_interactive, options.ip_qos_bulk);
@@ -2305,12 +2469,12 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem,
(r = sshpkt_put_u32(ssh, (u_int)ws.ws_row)) != 0 ||
(r = sshpkt_put_u32(ssh, (u_int)ws.ws_xpixel)) != 0 ||
(r = sshpkt_put_u32(ssh, (u_int)ws.ws_ypixel)) != 0)
- fatal("%s: build packet: %s", __func__, ssh_err(r));
+ fatal_fr(r, "build pty-req");
if (tiop == NULL)
tiop = get_saved_tio();
ssh_tty_make_modes(ssh, -1, tiop);
if ((r = sshpkt_send(ssh)) != 0)
- fatal("%s: send packet: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send pty-req");
/* XXX wait for reply */
c->client_tty = 1;
}
@@ -2339,15 +2503,7 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem,
free(name);
continue;
}
-
- debug("Sending env %s = %s", name, val);
- channel_request_start(ssh, id, "env", 0);
- if ((r = sshpkt_put_cstring(ssh, name)) != 0 ||
- (r = sshpkt_put_cstring(ssh, val)) != 0 ||
- (r = sshpkt_send(ssh)) != 0) {
- fatal("%s: send packet: %s",
- __func__, ssh_err(r));
- }
+ client_send_env(ssh, id, name, val);
free(name);
}
}
@@ -2359,13 +2515,7 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem,
continue;
}
*val++ = '\0';
-
- debug("Setting env %s = %s", name, val);
- channel_request_start(ssh, id, "env", 0);
- if ((r = sshpkt_put_cstring(ssh, name)) != 0 ||
- (r = sshpkt_put_cstring(ssh, val)) != 0 ||
- (r = sshpkt_send(ssh)) != 0)
- fatal("%s: send packet: %s", __func__, ssh_err(r));
+ client_send_env(ssh, id, name, val);
free(name);
}
@@ -2387,14 +2537,12 @@ client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem,
}
if ((r = sshpkt_put_stringb(ssh, cmd)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: send command: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send command");
} else {
channel_request_start(ssh, id, "shell", 1);
client_expect_confirm(ssh, id, "shell", CONFIRM_CLOSE);
- if ((r = sshpkt_send(ssh)) != 0) {
- fatal("%s: send shell request: %s",
- __func__, ssh_err(r));
- }
+ if ((r = sshpkt_send(ssh)) != 0)
+ fatal_fr(r, "send shell");
}
}
@@ -2433,7 +2581,7 @@ client_stop_mux(void)
* If we are in persist mode, or don't have a shell, signal that we
* should close when all active channels are closed.
*/
- if (options.control_persist || no_shell_flag) {
+ if (options.control_persist || options.session_type == SESSION_TYPE_NONE) {
session_closed = 1;
setproctitle("[stopped mux]");
}
diff --git a/compat.c b/compat.c
index 0624dc6de..0dbea68c6 100644
--- a/compat.c
+++ b/compat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: compat.c,v 1.113 2018/08/13 02:41:05 djm Exp $ */
+/* $OpenBSD: compat.c,v 1.119 2021/09/10 05:46:09 djm Exp $ */
/*
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
*
@@ -38,11 +38,9 @@
#include "match.h"
#include "kex.h"
-int datafellows = 0;
-
-/* datafellows bug compatibility */
-u_int
-compat_datafellows(const char *version)
+/* determine bug flags from SSH protocol banner */
+void
+compat_banner(struct ssh *ssh, const char *version)
{
int i;
static struct {
@@ -65,11 +63,12 @@ compat_datafellows(const char *version)
{ "OpenSSH_6.5*,"
"OpenSSH_6.6*", SSH_NEW_OPENSSH|SSH_BUG_CURVE25519PAD|
SSH_BUG_SIGTYPE},
+ { "OpenSSH_7.4*", SSH_NEW_OPENSSH|SSH_BUG_SIGTYPE|
+ SSH_BUG_SIGTYPE74},
{ "OpenSSH_7.0*,"
"OpenSSH_7.1*,"
"OpenSSH_7.2*,"
"OpenSSH_7.3*,"
- "OpenSSH_7.4*,"
"OpenSSH_7.5*,"
"OpenSSH_7.6*,"
"OpenSSH_7.7*", SSH_NEW_OPENSSH|SSH_BUG_SIGTYPE},
@@ -145,89 +144,63 @@ compat_datafellows(const char *version)
};
/* process table, return first match */
+ ssh->compat = 0;
for (i = 0; check[i].pat; i++) {
if (match_pattern_list(version, check[i].pat, 0) == 1) {
- debug("match: %s pat %s compat 0x%08x",
+ debug_f("match: %s pat %s compat 0x%08x",
version, check[i].pat, check[i].bugs);
- datafellows = check[i].bugs; /* XXX for now */
- return check[i].bugs;
- }
- }
- debug("no match: %s", version);
- return 0;
-}
-
-#define SEP ","
-int
-proto_spec(const char *spec)
-{
- char *s, *p, *q;
- int ret = SSH_PROTO_UNKNOWN;
-
- if (spec == NULL)
- return ret;
- q = s = strdup(spec);
- if (s == NULL)
- return ret;
- for ((p = strsep(&q, SEP)); p && *p != '\0'; (p = strsep(&q, SEP))) {
- switch (atoi(p)) {
- case 2:
- ret |= SSH_PROTO_2;
- break;
- default:
- logit("ignoring bad proto spec: '%s'.", p);
- break;
+ ssh->compat = check[i].bugs;
+ return;
}
}
- free(s);
- return ret;
+ debug_f("no match: %s", version);
}
char *
-compat_cipher_proposal(char *cipher_prop)
+compat_cipher_proposal(struct ssh *ssh, char *cipher_prop)
{
- if (!(datafellows & SSH_BUG_BIGENDIANAES))
+ if (!(ssh->compat & SSH_BUG_BIGENDIANAES))
return cipher_prop;
- debug2("%s: original cipher proposal: %s", __func__, cipher_prop);
- if ((cipher_prop = match_filter_blacklist(cipher_prop, "aes*")) == NULL)
- fatal("match_filter_blacklist failed");
- debug2("%s: compat cipher proposal: %s", __func__, cipher_prop);
+ debug2_f("original cipher proposal: %s", cipher_prop);
+ if ((cipher_prop = match_filter_denylist(cipher_prop, "aes*")) == NULL)
+ fatal("match_filter_denylist failed");
+ debug2_f("compat cipher proposal: %s", cipher_prop);
if (*cipher_prop == '\0')
fatal("No supported ciphers found");
return cipher_prop;
}
char *
-compat_pkalg_proposal(char *pkalg_prop)
+compat_pkalg_proposal(struct ssh *ssh, char *pkalg_prop)
{
- if (!(datafellows & SSH_BUG_RSASIGMD5))
+ if (!(ssh->compat & SSH_BUG_RSASIGMD5))
return pkalg_prop;
- debug2("%s: original public key proposal: %s", __func__, pkalg_prop);
- if ((pkalg_prop = match_filter_blacklist(pkalg_prop, "ssh-rsa")) == NULL)
- fatal("match_filter_blacklist failed");
- debug2("%s: compat public key proposal: %s", __func__, pkalg_prop);
+ debug2_f("original public key proposal: %s", pkalg_prop);
+ if ((pkalg_prop = match_filter_denylist(pkalg_prop, "ssh-rsa")) == NULL)
+ fatal("match_filter_denylist failed");
+ debug2_f("compat public key proposal: %s", pkalg_prop);
if (*pkalg_prop == '\0')
fatal("No supported PK algorithms found");
return pkalg_prop;
}
char *
-compat_kex_proposal(char *p)
+compat_kex_proposal(struct ssh *ssh, char *p)
{
- if ((datafellows & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0)
+ if ((ssh->compat & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0)
return p;
- debug2("%s: original KEX proposal: %s", __func__, p);
- if ((datafellows & SSH_BUG_CURVE25519PAD) != 0)
- if ((p = match_filter_blacklist(p,
+ debug2_f("original KEX proposal: %s", p);
+ if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0)
+ if ((p = match_filter_denylist(p,
"curve25519-sha256@libssh.org")) == NULL)
- fatal("match_filter_blacklist failed");
- if ((datafellows & SSH_OLD_DHGEX) != 0) {
- if ((p = match_filter_blacklist(p,
+ fatal("match_filter_denylist failed");
+ if ((ssh->compat & SSH_OLD_DHGEX) != 0) {
+ if ((p = match_filter_denylist(p,
"diffie-hellman-group-exchange-sha256,"
"diffie-hellman-group-exchange-sha1")) == NULL)
- fatal("match_filter_blacklist failed");
+ fatal("match_filter_denylist failed");
}
- debug2("%s: compat KEX proposal: %s", __func__, p);
+ debug2_f("compat KEX proposal: %s", p);
if (*p == '\0')
fatal("No supported key exchange algorithms found");
return p;
diff --git a/compat.h b/compat.h
index d611d33e7..167409b2b 100644
--- a/compat.h
+++ b/compat.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: compat.h,v 1.54 2018/08/13 02:41:05 djm Exp $ */
+/* $OpenBSD: compat.h,v 1.57 2021/06/06 03:40:39 djm Exp $ */
/*
* Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved.
@@ -27,14 +27,9 @@
#ifndef COMPAT_H
#define COMPAT_H
-#define SSH_PROTO_UNKNOWN 0x00
-#define SSH_PROTO_1 0x01
-#define SSH_PROTO_1_PREFERRED 0x02
-#define SSH_PROTO_2 0x04
-
#define SSH_BUG_UTF8TTYMODE 0x00000001
#define SSH_BUG_SIGTYPE 0x00000002
-/* #define unused 0x00000004 */
+#define SSH_BUG_SIGTYPE74 0x00000004
/* #define unused 0x00000008 */
#define SSH_OLD_SESSIONID 0x00000010
/* #define unused 0x00000020 */
@@ -63,11 +58,10 @@
#define SSH_BUG_HOSTKEYS 0x20000000
#define SSH_BUG_DHGEX_LARGE 0x40000000
-u_int compat_datafellows(const char *);
-int proto_spec(const char *);
-char *compat_cipher_proposal(char *);
-char *compat_pkalg_proposal(char *);
-char *compat_kex_proposal(char *);
+struct ssh;
-extern int datafellows;
+void compat_banner(struct ssh *, const char *);
+char *compat_cipher_proposal(struct ssh *, char *);
+char *compat_pkalg_proposal(struct ssh *, char *);
+char *compat_kex_proposal(struct ssh *, char *);
#endif
diff --git a/configure.ac b/configure.ac
index 460383757..413913a7c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -14,12 +14,23 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_INIT([OpenSSH], [Portable], [openssh-unix-dev@mindrot.org])
-AC_REVISION($Revision: 1.583 $)
+AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR([ssh.c])
AC_LANG([C])
-AC_CONFIG_HEADER([config.h])
+AC_CONFIG_HEADERS([config.h])
AC_PROG_CC([cc gcc])
+
+# XXX relax this after reimplementing logit() etc.
+AC_MSG_CHECKING([if $CC supports C99-style variadic macros])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+int f(int a, int b, int c) { return a + b + c; }
+#define F(a, ...) f(a, __VA_ARGS__)
+]], [[return F(1, 2, -3);]])],
+ [ AC_MSG_RESULT([yes]) ],
+ [ AC_MSG_ERROR([*** OpenSSH requires support for C99-style variadic macros]) ]
+)
+
AC_CANONICAL_HOST
AC_C_BIGENDIAN
@@ -34,8 +45,6 @@ AC_CHECK_TOOLS([AR], [ar])
AC_PATH_PROG([CAT], [cat])
AC_PATH_PROG([KILL], [kill])
AC_PATH_PROG([SED], [sed])
-AC_PATH_PROG([ENT], [ent])
-AC_SUBST([ENT])
AC_PATH_PROG([TEST_MINUS_S_SH], [bash])
AC_PATH_PROG([TEST_MINUS_S_SH], [ksh])
AC_PATH_PROG([TEST_MINUS_S_SH], [sh])
@@ -164,6 +173,7 @@ if test "$GCC" = "yes" || test "$GCC" = "egcs"; then
OSSH_CHECK_CFLAG_COMPILE([-Wformat-security])
OSSH_CHECK_CFLAG_COMPILE([-Wsizeof-pointer-memaccess])
OSSH_CHECK_CFLAG_COMPILE([-Wpointer-sign], [-Wno-pointer-sign])
+ OSSH_CHECK_CFLAG_COMPILE([-Wunused-parameter], [-Wno-unused-parameter])
OSSH_CHECK_CFLAG_COMPILE([-Wunused-result], [-Wno-unused-result])
OSSH_CHECK_CFLAG_COMPILE([-Wimplicit-fallthrough])
OSSH_CHECK_CFLAG_COMPILE([-fno-strict-aliasing])
@@ -287,6 +297,26 @@ typedef void foo(const char *, ...) __attribute__((format(printf, 1, 2)));]],
[compiler does not accept __attribute__ on prototype args]) ]
)
+AC_MSG_CHECKING([if compiler supports variable length arrays])
+AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[#include <stdlib.h>]],
+ [[ int i; for (i=0; i<3; i++){int a[i]; a[i-1]=0;} exit(0); ]])],
+ [ AC_MSG_RESULT([yes])
+ AC_DEFINE(VARIABLE_LENGTH_ARRAYS, [1],
+ [compiler supports variable length arrays]) ],
+ [ AC_MSG_RESULT([no]) ]
+)
+
+AC_MSG_CHECKING([if compiler accepts variable declarations after code])
+AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[#include <stdlib.h>]],
+ [[ int a; a = 1; int b = 1; exit(a-b); ]])],
+ [ AC_MSG_RESULT([yes])
+ AC_DEFINE(VARIABLE_DECLARATION_AFTER_CODE, [1],
+ [compiler variable declarations after code]) ],
+ [ AC_MSG_RESULT([no]) ]
+)
+
if test "x$no_attrib_nonnull" != "x1" ; then
AC_DEFINE([HAVE_ATTRIBUTE__NONNULL__], [1], [Have attribute nonnull])
fi
@@ -424,6 +454,7 @@ AC_CHECK_HEADERS([ \
sys/ndir.h \
sys/poll.h \
sys/prctl.h \
+ sys/procctl.h \
sys/pstat.h \
sys/ptrace.h \
sys/random.h \
@@ -652,7 +683,9 @@ case "$host" in
*-*-darwin*)
use_pie=auto
AC_MSG_CHECKING([if we have working getaddrinfo])
- AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include <mach-o/dyld.h>
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[
+#include <mach-o/dyld.h>
+#include <stdlib.h>
main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
exit(0);
else
@@ -912,6 +945,9 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
;;
esac
;;
+ riscv64-*)
+ seccomp_audit_arch=AUDIT_ARCH_RISCV64
+ ;;
esac
if test "x$seccomp_audit_arch" != "x" ; then
AC_MSG_RESULT(["$seccomp_audit_arch"])
@@ -1233,7 +1269,7 @@ EOD
esac
AC_MSG_CHECKING([compiler and flags for sanity])
-AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h> ]], [[ exit(0); ]])],
+AC_RUN_IFELSE([AC_LANG_PROGRAM([[ #include <stdlib.h> ]], [[ exit(0); ]])],
[ AC_MSG_RESULT([yes]) ],
[
AC_MSG_RESULT([no])
@@ -1257,6 +1293,7 @@ AC_CHECK_FUNCS([dirname], [AC_CHECK_HEADERS([libgen.h])] , [
[AC_LANG_SOURCE([[
#include <libgen.h>
#include <string.h>
+#include <stdlib.h>
int main(int argc, char **argv) {
char *s, buf[32];
@@ -1420,6 +1457,10 @@ AC_CHECK_FUNCS([fmt_scaled scan_scaled login logout openpty updwtmp logwtmp])
AC_SEARCH_LIBS([inet_ntop], [resolv nsl])
AC_SEARCH_LIBS([gethostbyname], [resolv nsl])
+# Some Linux distribtions ship the BSD libc hashing functions in
+# separate libraries.
+AC_SEARCH_LIBS([SHA256Update], [md bsd])
+
# "Particular Function Checks"
# see https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Particular-Functions.html
AC_FUNC_STRFTIME
@@ -1508,7 +1549,9 @@ AC_MSG_CHECKING([whether struct dirent allocates space for d_name])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <sys/types.h>
-#include <dirent.h>]],
+#include <dirent.h>
+#include <stdlib.h>
+ ]],
[[
struct dirent d;
exit(sizeof(d.d_name)<=sizeof(char));
@@ -1622,7 +1665,10 @@ AC_ARG_WITH([libedit],
)
AC_MSG_CHECKING([if libedit version is compatible])
AC_COMPILE_IFELSE(
- [AC_LANG_PROGRAM([[ #include <histedit.h> ]],
+ [AC_LANG_PROGRAM([[
+#include <histedit.h>
+#include <stdlib.h>
+ ]],
[[
int i = H_SETSIZE;
el_init("", NULL, NULL, NULL);
@@ -1774,6 +1820,7 @@ AC_CHECK_FUNCS([ \
err \
errx \
explicit_bzero \
+ explicit_memset \
fchmod \
fchmodat \
fchown \
@@ -1809,6 +1856,7 @@ AC_CHECK_FUNCS([ \
llabs \
localtime_r \
login_getcapbool \
+ login_getpwclass \
md5_crypt \
memmem \
memmove \
@@ -1821,6 +1869,8 @@ AC_CHECK_FUNCS([ \
pledge \
poll \
prctl \
+ procctl \
+ pselect \
pstat \
raise \
readpassphrase \
@@ -1971,7 +2021,7 @@ AC_SEARCH_LIBS([clock_gettime], [rt],
dnl check if we need -D_REENTRANT for localtime_r declaration.
AC_CHECK_DECL([localtime_r], [],
- [ saved_CPPFLAGS="$CFLAGS"
+ [ saved_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS -D_REENTRANT"
unset ac_cv_have_decl_localtime_r
AC_CHECK_DECL([localtime_r], [],
@@ -2112,7 +2162,11 @@ AC_CHECK_FUNCS([setresgid], [
AC_MSG_CHECKING([for working fflush(NULL)])
AC_RUN_IFELSE(
- [AC_LANG_PROGRAM([[#include <stdio.h>]], [[fflush(NULL); exit(0);]])],
+ [AC_LANG_PROGRAM([[
+#include <stdio.h>
+#include <stdlib.h>
+ ]],
+ [[fflush(NULL); exit(0);]])],
AC_MSG_RESULT([yes]),
[AC_MSG_RESULT([no])
AC_DEFINE([FFLUSH_NULL_BUG], [1],
@@ -2148,7 +2202,10 @@ AC_CHECK_FUNC([getpagesize],
if test "x$ac_cv_func_snprintf" = "xyes" ; then
AC_MSG_CHECKING([whether snprintf correctly terminates long strings])
AC_RUN_IFELSE(
- [AC_LANG_PROGRAM([[ #include <stdio.h> ]],
+ [AC_LANG_PROGRAM([[
+#include <stdio.h>
+#include <stdlib.h>
+ ]],
[[
char b[5];
snprintf(b,5,"123456789");
@@ -2171,6 +2228,8 @@ if test "x$ac_cv_func_snprintf" = "xyes" ; then
[AC_LANG_PROGRAM([[
#include <sys/types.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
]],
[[
size_t a = 1, b = 2;
@@ -2257,39 +2316,14 @@ if test "x$ac_cv_func_getpeereid" != "xyes" -a "x$ac_cv_func_getpeerucred" != "x
])
fi
-dnl see whether mkstemp() requires XXXXXX
-if test "x$ac_cv_func_mkdtemp" = "xyes" ; then
-AC_MSG_CHECKING([for (overly) strict mkstemp])
-AC_RUN_IFELSE(
- [AC_LANG_PROGRAM([[
-#include <stdlib.h>
- ]], [[
- char template[]="conftest.mkstemp-test";
- if (mkstemp(template) == -1)
- exit(1);
- unlink(template);
- exit(0);
- ]])],
- [
- AC_MSG_RESULT([no])
- ],
- [
- AC_MSG_RESULT([yes])
- AC_DEFINE([HAVE_STRICT_MKSTEMP], [1], [Silly mkstemp()])
- ],
- [
- AC_MSG_RESULT([yes])
- AC_DEFINE([HAVE_STRICT_MKSTEMP])
- ]
-)
-fi
-
dnl make sure that openpty does not reacquire controlling terminal
if test ! -z "$check_for_openpty_ctty_bug"; then
AC_MSG_CHECKING([if openpty correctly handles controlling tty])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -2336,6 +2370,7 @@ if test "x$ac_cv_func_getaddrinfo" = "xyes" && \
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdio.h>
+#include <stdlib.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
@@ -2404,6 +2439,7 @@ if test "x$ac_cv_func_getaddrinfo" = "xyes" && \
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdio.h>
+#include <stdlib.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
@@ -2466,7 +2502,10 @@ fi
if test "x$check_for_conflicting_getspnam" = "x1"; then
AC_MSG_CHECKING([for conflicting getspnam in shadow.h])
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <shadow.h> ]],
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <shadow.h>
+#include <stdlib.h>
+ ]],
[[ exit(0); ]])],
[
AC_MSG_RESULT([no])
@@ -2496,6 +2535,7 @@ if test "x$ac_cv_func_strnvis" = "xyes"; then
#include <signal.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <vis.h>
static void sighandler(int sig) { _exit(1); }
]], [[
@@ -2524,6 +2564,7 @@ AC_RUN_IFELSE(
#include <sys/time.h>
#include <stdlib.h>
#include <signal.h>
+#include <unistd.h>
static void sighandler(int sig) { }
]], [[
int r;
@@ -2680,6 +2721,7 @@ if test "x$openssl" = "xyes" ; then
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdio.h>
+ #include <stdlib.h>
#include <string.h>
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
@@ -2721,7 +2763,8 @@ if test "x$openssl" = "xyes" ; then
;;
101*) ;; # 1.1.x
200*) ;; # LibreSSL
- 300*) ;; # OpenSSL development branch.
+ 300*) ;; # OpenSSL 3
+ 301*) ;; # OpenSSL development branch.
*)
AC_MSG_ERROR([Unknown/unsupported OpenSSL version ("$ssl_library_ver")])
;;
@@ -2741,6 +2784,7 @@ if test "x$openssl" = "xyes" ; then
AC_MSG_CHECKING([whether OpenSSL's headers match the library])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
+ #include <stdlib.h>
#include <string.h>
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
@@ -2841,6 +2885,7 @@ if test "x$openssl" = "xyes" ; then
EVP_CIPHER_CTX_iv \
EVP_CIPHER_CTX_iv_noconst \
EVP_CIPHER_CTX_get_iv \
+ EVP_CIPHER_CTX_get_updated_iv \
EVP_CIPHER_CTX_set_iv \
RSA_get0_crt_params \
RSA_get0_factors \
@@ -2880,6 +2925,7 @@ if test "x$openssl" = "xyes" ; then
AC_MSG_CHECKING([whether OpenSSL has crippled AES support])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[
+ #include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
]], [[
@@ -2899,6 +2945,7 @@ if test "x$openssl" = "xyes" ; then
AC_MSG_CHECKING([whether OpenSSL has AES CTR via EVP])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[
+ #include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
]], [[
@@ -2920,6 +2967,7 @@ if test "x$openssl" = "xyes" ; then
AC_MSG_CHECKING([whether OpenSSL has AES GCM via EVP])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[
+ #include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
]], [[
@@ -2947,6 +2995,7 @@ if test "x$openssl" = "xyes" ; then
AC_MSG_CHECKING([if EVP_DigestUpdate returns an int])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([[
+ #include <stdlib.h>
#include <string.h>
#include <openssl/evp.h>
]], [[
@@ -3033,6 +3082,7 @@ if test "x$openssl" = "xyes" ; then
AC_MSG_CHECKING([if OpenSSL's NID_secp521r1 is functional])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
+ #include <stdlib.h>
#include <openssl/ec.h>
#include <openssl/ecdh.h>
#include <openssl/ecdsa.h>
@@ -3053,7 +3103,6 @@ if test "x$openssl" = "xyes" ; then
AC_MSG_RESULT([no])
)
- COMMENT_OUT_ECC="#no ecc#"
TEST_SSH_ECC=no
if test x$enable_nistp256 = x1 || test x$enable_nistp384 = x1 || \
@@ -3068,7 +3117,6 @@ if test "x$openssl" = "xyes" ; then
AC_DEFINE([OPENSSL_HAS_NISTP256], [1],
[libcrypto has NID_X9_62_prime256v1])
TEST_SSH_ECC=yes
- COMMENT_OUT_ECC=""
else
unsupported_algorithms="$unsupported_algorithms \
ecdsa-sha2-nistp256 \
@@ -3078,7 +3126,6 @@ if test "x$openssl" = "xyes" ; then
if test x$enable_nistp384 = x1; then
AC_DEFINE([OPENSSL_HAS_NISTP384], [1], [libcrypto has NID_secp384r1])
TEST_SSH_ECC=yes
- COMMENT_OUT_ECC=""
else
unsupported_algorithms="$unsupported_algorithms \
ecdsa-sha2-nistp384 \
@@ -3088,7 +3135,6 @@ if test "x$openssl" = "xyes" ; then
if test x$enable_nistp521 = x1; then
AC_DEFINE([OPENSSL_HAS_NISTP521], [1], [libcrypto has NID_secp521r1])
TEST_SSH_ECC=yes
- COMMENT_OUT_ECC=""
else
unsupported_algorithms="$unsupported_algorithms \
ecdh-sha2-nistp521 \
@@ -3097,7 +3143,6 @@ if test "x$openssl" = "xyes" ; then
fi
AC_SUBST([TEST_SSH_ECC])
- AC_SUBST([COMMENT_OUT_ECC])
else
AC_CHECK_LIB([crypt], [crypt], [LIBS="$LIBS -lcrypt"])
AC_CHECK_FUNCS([crypt])
@@ -3173,6 +3218,16 @@ if test "x$enable_sk" = "xyes" -a "x$enable_sk_internal" = "xyes" ; then
], [ AC_MSG_ERROR([no usable libfido2 found]) ],
[ $OTHERLIBS ]
)
+ saved_LIBS="$LIBS"
+ LIBS="$LIBS $LIBFIDO2"
+ AC_CHECK_FUNCS([ \
+ fido_cred_prot \
+ fido_cred_set_prot \
+ fido_dev_get_touch_begin \
+ fido_dev_get_touch_status \
+ fido_dev_supports_cred_prot \
+ ])
+ LIBS="$saved_LIBS"
AC_CHECK_HEADER([fido.h], [],
AC_MSG_ERROR([missing fido.h from libfido2]))
AC_CHECK_HEADER([fido/credman.h], [],
@@ -3205,6 +3260,7 @@ if test "x$openssl" = "xyes" ; then
AC_MSG_CHECKING([whether OpenSSL's PRNG is internally seeded])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
+ #include <stdlib.h>
#include <string.h>
#include <openssl/rand.h>
]], [[
@@ -3616,7 +3672,7 @@ if test ! -z "$SONY" ; then
LIBS="$LIBS -liberty";
fi
-# Check for long long datatypes
+# Check for long long datatypes
AC_CHECK_TYPES([long long, unsigned long long, long double])
# Check datatype sizes
@@ -3624,6 +3680,16 @@ AC_CHECK_SIZEOF([short int])
AC_CHECK_SIZEOF([int])
AC_CHECK_SIZEOF([long int])
AC_CHECK_SIZEOF([long long int])
+AC_CHECK_SIZEOF([time_t], [], [[
+ #include <sys/types.h>
+ #ifdef HAVE_SYS_TIME_H
+ # include <sys/time.h>
+ #endif
+ #ifdef HAVE_TIME_H
+ # include <time.h>
+ #endif
+ ]]
+)
# Sanity check long long for some platforms (AIX)
if test "x$ac_cv_sizeof_long_long_int" = "x4" ; then
@@ -3636,6 +3702,7 @@ if test -z "$have_llong_max" && test -z "$have_long_long_max"; then
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdio.h>
+#include <stdlib.h>
/* Why is this so damn hard? */
#ifdef __GNUC__
# undef __GNUC__
@@ -3924,7 +3991,7 @@ AC_CHECK_TYPES([intmax_t, uintmax_t], , , [
TYPE_SOCKLEN_T
-AC_CHECK_TYPES([sig_atomic_t], , , [#include <signal.h>])
+AC_CHECK_TYPES([sig_atomic_t, sighandler_t], , , [#include <signal.h>])
AC_CHECK_TYPES([fsblkcnt_t, fsfilcnt_t], , , [
#include <sys/types.h>
#ifdef HAVE_SYS_BITYPES_H
@@ -4101,8 +4168,6 @@ if test "x$ac_cv_have_struct_addrinfo" = "xyes" ; then
[define if you have struct addrinfo data type])
fi
-AC_HEADER_TIME
-
AC_CACHE_CHECK([for struct timeval], ac_cv_have_struct_timeval, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <sys/time.h> ]],
[[ struct timeval tv; tv.tv_sec = 1;]])],
@@ -4117,15 +4182,11 @@ fi
AC_CACHE_CHECK([for struct timespec], ac_cv_have_struct_timespec, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
- #ifdef TIME_WITH_SYS_TIME
+ #ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
+ #endif
+ #ifdef HAVE_TIME_H
# include <time.h>
- #else
- # ifdef HAVE_SYS_TIME_H
- # include <sys/time.h>
- # else
- # include <time.h>
- # endif
#endif
]],
[[ struct timespec ts; ts.tv_sec = 1;]])],
@@ -4151,6 +4212,7 @@ dnl test snprintf (broken on SCO w/gcc)
AC_RUN_IFELSE(
[AC_LANG_SOURCE([[
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SNPRINTF
main()
@@ -4195,6 +4257,7 @@ OSSH_CHECK_HEADER_FOR_FIELD([ut_exit], [utmp.h], [HAVE_EXIT_IN_UTMP])
OSSH_CHECK_HEADER_FOR_FIELD([ut_time], [utmp.h], [HAVE_TIME_IN_UTMP])
OSSH_CHECK_HEADER_FOR_FIELD([ut_time], [utmpx.h], [HAVE_TIME_IN_UTMPX])
OSSH_CHECK_HEADER_FOR_FIELD([ut_tv], [utmpx.h], [HAVE_TV_IN_UTMPX])
+OSSH_CHECK_HEADER_FOR_FIELD([ut_ss], [utmpx.h], [HAVE_SS_IN_UTMPX])
AC_CHECK_MEMBERS([struct stat.st_blksize])
AC_CHECK_MEMBERS([struct stat.st_mtim])
@@ -4253,6 +4316,7 @@ AC_CACHE_CHECK([for msg_accrights field in struct msghdr],
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
+#include <stdlib.h>
]], [[
#ifdef msg_accrights
#error "msg_accrights is a macro"
@@ -4314,6 +4378,7 @@ AC_CACHE_CHECK([for msg_control field in struct msghdr],
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
+#include <stdlib.h>
]], [[
#ifdef msg_control
#error "msg_control is a macro"
@@ -4334,7 +4399,7 @@ if test "x$ac_cv_have_control_in_msghdr" = "xyes" ; then
fi
AC_CACHE_CHECK([if libc defines __progname], ac_cv_libc_defines___progname, [
- AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h> ]],
[[ extern char *__progname; printf("%s", __progname); ]])],
[ ac_cv_libc_defines___progname="yes" ],
[ ac_cv_libc_defines___progname="no"
@@ -4406,7 +4471,7 @@ if test "x$ac_cv_have_getopt_optreset" = "xyes" ; then
fi
AC_CACHE_CHECK([if libc defines sys_errlist], ac_cv_libc_defines_sys_errlist, [
- AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h> ]],
[[ extern const char *const sys_errlist[]; printf("%s", sys_errlist[0]);]])],
[ ac_cv_libc_defines_sys_errlist="yes" ],
[ ac_cv_libc_defines_sys_errlist="no"
@@ -4419,7 +4484,7 @@ fi
AC_CACHE_CHECK([if libc defines sys_nerr], ac_cv_libc_defines_sys_nerr, [
- AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h> ]],
[[ extern int sys_nerr; printf("%i", sys_nerr);]])],
[ ac_cv_libc_defines_sys_nerr="yes" ],
[ ac_cv_libc_defines_sys_nerr="no"
@@ -4513,13 +4578,10 @@ AC_ARG_WITH([selinux],
LIBS="$LIBS -lselinux"
],
AC_MSG_ERROR([SELinux support requires libselinux library]))
- SSHLIBS="$SSHLIBS $LIBSELINUX"
- SSHDLIBS="$SSHDLIBS $LIBSELINUX"
AC_CHECK_FUNCS([getseuserbyname get_default_context_with_level])
- LIBS="$save_LIBS"
+ LIBS="$save_LIBS $LIBSELINUX"
fi ]
)
-AC_SUBST([SSHLIBS])
AC_SUBST([SSHDLIBS])
# Check whether user wants Kerberos 5 support
@@ -4536,22 +4598,30 @@ AC_ARG_WITH([kerberos5],
AC_DEFINE([KRB5], [1], [Define if you want Kerberos 5 support])
KRB5_MSG="yes"
- AC_PATH_TOOL([KRB5CONF], [krb5-config],
- [$KRB5ROOT/bin/krb5-config],
- [$KRB5ROOT/bin:$PATH])
- if test -x $KRB5CONF ; then
- K5CFLAGS="`$KRB5CONF --cflags`"
- K5LIBS="`$KRB5CONF --libs`"
+ AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no])
+ use_pkgconfig_for_krb5=
+ if test "x$PKGCONFIG" != "xno"; then
+ AC_MSG_CHECKING([if $PKGCONFIG knows about kerberos5])
+ if "$PKGCONFIG" krb5; then
+ AC_MSG_RESULT([yes])
+ use_pkgconfig_for_krb5=yes
+ else
+ AC_MSG_RESULT([no])
+ fi
+ fi
+ if test "x$use_pkgconfig_for_krb5" = "xyes"; then
+ K5CFLAGS=`$PKGCONFIG --cflags krb5`
+ K5LIBS=`$PKGCONFIG --libs krb5`
CPPFLAGS="$CPPFLAGS $K5CFLAGS"
AC_MSG_CHECKING([for gssapi support])
- if $KRB5CONF | grep gssapi >/dev/null ; then
+ if "$PKGCONFIG" krb5-gssapi; then
AC_MSG_RESULT([yes])
AC_DEFINE([GSSAPI], [1],
[Define this if you want GSSAPI
support in the version 2 protocol])
- GSSCFLAGS="`$KRB5CONF --cflags gssapi`"
- GSSLIBS="`$KRB5CONF --libs gssapi`"
+ GSSCFLAGS="`$PKGCONFIG --cflags krb5-gssapi`"
+ GSSLIBS="`$PKGCONFIG --libs krb5-gssapi`"
CPPFLAGS="$CPPFLAGS $GSSCFLAGS"
else
AC_MSG_RESULT([no])
@@ -4566,51 +4636,82 @@ AC_ARG_WITH([kerberos5],
[AC_MSG_RESULT([no])
])
else
- CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include"
- LDFLAGS="$LDFLAGS -L${KRB5ROOT}/lib"
- AC_MSG_CHECKING([whether we are using Heimdal])
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <krb5.h>
- ]], [[ char *tmp = heimdal_version; ]])],
+ AC_PATH_TOOL([KRB5CONF], [krb5-config],
+ [$KRB5ROOT/bin/krb5-config],
+ [$KRB5ROOT/bin:$PATH])
+ if test -x $KRB5CONF ; then
+ K5CFLAGS="`$KRB5CONF --cflags`"
+ K5LIBS="`$KRB5CONF --libs`"
+ CPPFLAGS="$CPPFLAGS $K5CFLAGS"
+
+ AC_MSG_CHECKING([for gssapi support])
+ if $KRB5CONF | grep gssapi >/dev/null ; then
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([GSSAPI], [1],
+ [Define this if you want GSSAPI
+ support in the version 2 protocol])
+ GSSCFLAGS="`$KRB5CONF --cflags gssapi`"
+ GSSLIBS="`$KRB5CONF --libs gssapi`"
+ CPPFLAGS="$CPPFLAGS $GSSCFLAGS"
+ else
+ AC_MSG_RESULT([no])
+ fi
+ AC_MSG_CHECKING([whether we are using Heimdal])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <krb5.h>
+ ]], [[ char *tmp = heimdal_version; ]])],
[ AC_MSG_RESULT([yes])
- AC_DEFINE([HEIMDAL])
- K5LIBS="-lkrb5"
- K5LIBS="$K5LIBS -lcom_err -lasn1"
- AC_CHECK_LIB([roken], [net_write],
- [K5LIBS="$K5LIBS -lroken"])
- AC_CHECK_LIB([des], [des_cbc_encrypt],
- [K5LIBS="$K5LIBS -ldes"])
- ], [ AC_MSG_RESULT([no])
- K5LIBS="-lkrb5 -lk5crypto -lcom_err"
- ])
- AC_SEARCH_LIBS([dn_expand], [resolv])
+ AC_DEFINE([HEIMDAL], [1],
+ [Define this if you are using the Heimdal
+ version of Kerberos V5]) ],
+ [AC_MSG_RESULT([no])
+ ])
+ else
+ CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include"
+ LDFLAGS="$LDFLAGS -L${KRB5ROOT}/lib"
+ AC_MSG_CHECKING([whether we are using Heimdal])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <krb5.h>
+ ]], [[ char *tmp = heimdal_version; ]])],
+ [ AC_MSG_RESULT([yes])
+ AC_DEFINE([HEIMDAL])
+ K5LIBS="-lkrb5"
+ K5LIBS="$K5LIBS -lcom_err -lasn1"
+ AC_CHECK_LIB([roken], [net_write],
+ [K5LIBS="$K5LIBS -lroken"])
+ AC_CHECK_LIB([des], [des_cbc_encrypt],
+ [K5LIBS="$K5LIBS -ldes"])
+ ], [ AC_MSG_RESULT([no])
+ K5LIBS="-lkrb5 -lk5crypto -lcom_err"
+ ])
+ AC_SEARCH_LIBS([dn_expand], [resolv])
- AC_CHECK_LIB([gssapi_krb5], [gss_init_sec_context],
- [ AC_DEFINE([GSSAPI])
- GSSLIBS="-lgssapi_krb5" ],
- [ AC_CHECK_LIB([gssapi], [gss_init_sec_context],
+ AC_CHECK_LIB([gssapi_krb5], [gss_init_sec_context],
[ AC_DEFINE([GSSAPI])
- GSSLIBS="-lgssapi" ],
- [ AC_CHECK_LIB([gss], [gss_init_sec_context],
+ GSSLIBS="-lgssapi_krb5" ],
+ [ AC_CHECK_LIB([gssapi], [gss_init_sec_context],
[ AC_DEFINE([GSSAPI])
- GSSLIBS="-lgss" ],
- AC_MSG_WARN([Cannot find any suitable gss-api library - build may fail]))
+ GSSLIBS="-lgssapi" ],
+ [ AC_CHECK_LIB([gss], [gss_init_sec_context],
+ [ AC_DEFINE([GSSAPI])
+ GSSLIBS="-lgss" ],
+ AC_MSG_WARN([Cannot find any suitable gss-api library - build may fail]))
+ ])
])
- ])
- AC_CHECK_HEADER([gssapi.h], ,
- [ unset ac_cv_header_gssapi_h
- CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
- AC_CHECK_HEADERS([gssapi.h], ,
- AC_MSG_WARN([Cannot find any suitable gss-api header - build may fail])
- )
- ]
- )
+ AC_CHECK_HEADER([gssapi.h], ,
+ [ unset ac_cv_header_gssapi_h
+ CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
+ AC_CHECK_HEADERS([gssapi.h], ,
+ AC_MSG_WARN([Cannot find any suitable gss-api header - build may fail])
+ )
+ ]
+ )
- oldCPP="$CPPFLAGS"
- CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
- AC_CHECK_HEADER([gssapi_krb5.h], ,
- [ CPPFLAGS="$oldCPP" ])
+ oldCPP="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS -I${KRB5ROOT}/include/gssapi"
+ AC_CHECK_HEADER([gssapi_krb5.h], ,
+ [ CPPFLAGS="$oldCPP" ])
+ fi
fi
if test -n "${rpath_opt}" ; then
LDFLAGS="$LDFLAGS ${rpath_opt}${KRB5ROOT}/lib"
@@ -4731,6 +4832,7 @@ AC_ARG_WITH([maildir],
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([[
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
@@ -4975,6 +5077,7 @@ otherwise scp will not work.])
[AC_LANG_PROGRAM([[
/* find out what STDPATH is */
#include <stdio.h>
+#include <stdlib.h>
#ifdef HAVE_PATHS_H
# include <paths.h>
#endif
@@ -5480,9 +5583,6 @@ echo " Libraries: ${LIBS}"
if test ! -z "${SSHDLIBS}"; then
echo " +for sshd: ${SSHDLIBS}"
fi
-if test ! -z "${SSHLIBS}"; then
-echo " +for ssh: ${SSHLIBS}"
-fi
echo ""
diff --git a/contrib/Makefile b/contrib/Makefile
index 3a36387b3..45d878bdc 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"
+ @echo "Valid targets: gnome-ssh-askpass1 gnome-ssh-askpass2 gnome-ssk-askpass3"
gnome-ssh-askpass1: gnome-ssh-askpass1.c
$(CC) $(CFLAGS) `gnome-config --cflags gnome gnomeui` \
@@ -13,9 +13,9 @@ gnome-ssh-askpass2: gnome-ssh-askpass2.c
gnome-ssh-askpass2.c -o gnome-ssh-askpass2 \
`$(PKG_CONFIG) --libs gtk+-2.0 x11`
-gnome-ssh-askpass3: gnome-ssh-askpass2.c
+gnome-ssh-askpass3: gnome-ssh-askpass3.c
$(CC) $(CFLAGS) `$(PKG_CONFIG) --cflags gtk+-3.0` \
- gnome-ssh-askpass2.c -o gnome-ssh-askpass3 \
+ gnome-ssh-askpass3.c -o gnome-ssh-askpass3 \
`$(PKG_CONFIG) --libs gtk+-3.0 x11`
clean:
diff --git a/contrib/gnome-ssh-askpass1.c b/contrib/gnome-ssh-askpass1.c
index 4d51032d1..4c92c177b 100644
--- a/contrib/gnome-ssh-askpass1.c
+++ b/contrib/gnome-ssh-askpass1.c
@@ -137,9 +137,10 @@ passphrase_dialog(char *message)
gnome_dialog_close(GNOME_DIALOG(dialog));
return (result == 0 ? 0 : -1);
- /* At least one grab failed - ungrab what we got, and report
- the failure to the user. Note that XGrabServer() cannot
- fail. */
+ /*
+ * At least one grab failed - ungrab what we got, and report the
+ * failure to the user. Note that XGrabServer() cannot fail.
+ */
nograbkb:
gdk_pointer_ungrab(GDK_CURRENT_TIME);
nograb:
diff --git a/contrib/gnome-ssh-askpass2.c b/contrib/gnome-ssh-askpass2.c
index bc83a2d67..a62f98152 100644
--- a/contrib/gnome-ssh-askpass2.c
+++ b/contrib/gnome-ssh-askpass2.c
@@ -56,9 +56,11 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
+
#include <X11/Xlib.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
+#include <gdk/gdkkeysyms.h>
static void
report_failed_grab (GtkWidget *parent_window, const char *what)
@@ -66,11 +68,9 @@ report_failed_grab (GtkWidget *parent_window, const char *what)
GtkWidget *err;
err = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
- "Could not grab %s. "
- "A malicious client may be eavesdropping "
- "on your session.", what);
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ "Could not grab %s. A malicious client may be eavesdropping "
+ "on your session.", what);
gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER);
gtk_dialog_run(GTK_DIALOG(err));
@@ -85,6 +85,67 @@ ok_dialog(GtkWidget *entry, gpointer dialog)
gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
}
+static gboolean
+check_none(GtkWidget *widget, GdkEventKey *event, gpointer dialog)
+{
+ switch (event->keyval) {
+ case GDK_KEY_Escape:
+ /* esc -> close dialog */
+ gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE);
+ return TRUE;
+ case GDK_KEY_Tab:
+ /* tab -> focus close button */
+ gtk_widget_grab_focus(gtk_dialog_get_widget_for_response(
+ dialog, GTK_RESPONSE_CLOSE));
+ return TRUE;
+ default:
+ /* eat all other key events */
+ return TRUE;
+ }
+}
+
+static int
+parse_env_hex_color(const char *env, GdkColor *c)
+{
+ const char *s;
+ unsigned long ul;
+ char *ep;
+ size_t n;
+
+ if ((s = getenv(env)) == NULL)
+ return 0;
+
+ memset(c, 0, sizeof(*c));
+
+ /* Permit hex rgb or rrggbb optionally prefixed by '#' or '0x' */
+ if (*s == '#')
+ s++;
+ else if (strncmp(s, "0x", 2) == 0)
+ s += 2;
+ n = strlen(s);
+ if (n != 3 && n != 6)
+ goto bad;
+ ul = strtoul(s, &ep, 16);
+ if (*ep != '\0' || ul > 0xffffff) {
+ bad:
+ fprintf(stderr, "Invalid $%s - invalid hex color code\n", env);
+ return 0;
+ }
+ /* Valid hex sequence; expand into a GdkColor */
+ if (n == 3) {
+ /* 4-bit RGB */
+ c->red = ((ul >> 8) & 0xf) << 12;
+ c->green = ((ul >> 4) & 0xf) << 12;
+ c->blue = (ul & 0xf) << 12;
+ } else {
+ /* 8-bit RGB */
+ c->red = ((ul >> 16) & 0xff) << 8;
+ c->green = ((ul >> 8) & 0xff) << 8;
+ c->blue = (ul & 0xff) << 8;
+ }
+ return 1;
+}
+
static int
passphrase_dialog(char *message, int prompt_type)
{
@@ -94,11 +155,16 @@ passphrase_dialog(char *message, int prompt_type)
int buttons, default_response;
GtkWidget *parent_window, *dialog, *entry;
GdkGrabStatus status;
+ GdkColor fg, bg;
+ int fg_set = 0, bg_set = 0;
grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL);
grab_pointer = (getenv("GNOME_SSH_ASKPASS_GRAB_POINTER") != NULL);
grab_tries = 0;
+ fg_set = parse_env_hex_color("GNOME_SSH_ASKPASS_FG_COLOR", &fg);
+ bg_set = parse_env_hex_color("GNOME_SSH_ASKPASS_BG_COLOR", &bg);
+
/* Create an invisible parent window so that GtkDialog doesn't
* complain. */
parent_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
@@ -127,17 +193,38 @@ passphrase_dialog(char *message, int prompt_type)
gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_response);
gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
- if (prompt_type == PROMPT_ENTRY) {
+ if (fg_set)
+ gtk_widget_modify_fg(dialog, GTK_STATE_NORMAL, &fg);
+ if (bg_set)
+ gtk_widget_modify_bg(dialog, GTK_STATE_NORMAL, &bg);
+
+ if (prompt_type == PROMPT_ENTRY || prompt_type == PROMPT_NONE) {
entry = gtk_entry_new();
+ if (fg_set)
+ gtk_widget_modify_fg(entry, GTK_STATE_NORMAL, &fg);
+ if (bg_set)
+ gtk_widget_modify_bg(entry, GTK_STATE_NORMAL, &bg);
gtk_box_pack_start(
GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
entry, FALSE, FALSE, 0);
gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
gtk_widget_grab_focus(entry);
- gtk_widget_show(entry);
- /* Make <enter> close dialog */
- g_signal_connect(G_OBJECT(entry), "activate",
- G_CALLBACK(ok_dialog), dialog);
+ if (prompt_type == PROMPT_ENTRY) {
+ gtk_widget_show(entry);
+ /* Make <enter> close dialog */
+ g_signal_connect(G_OBJECT(entry), "activate",
+ G_CALLBACK(ok_dialog), dialog);
+ } else {
+ /*
+ * Ensure the 'close' button is not focused by default
+ * but is still reachable via tab. This is a bit of a
+ * hack - it uses a hidden entry that responds to a
+ * couple of keypress events (escape and tab only).
+ */
+ gtk_widget_realize(entry);
+ g_signal_connect(G_OBJECT(entry), "key_press_event",
+ G_CALLBACK(check_none), dialog);
+ }
}
/* Grab focus */
diff --git a/contrib/gnome-ssh-askpass3.c b/contrib/gnome-ssh-askpass3.c
new file mode 100644
index 000000000..e1a0533ef
--- /dev/null
+++ b/contrib/gnome-ssh-askpass3.c
@@ -0,0 +1,305 @@
+/*
+ * 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.
+ */
+
+/* GTK2 support by Nalin Dahyabhai <nalin@redhat.com> */
+
+/*
+ * This is a simple GNOME SSH passphrase grabber. To use it, set the
+ * environment variable SSH_ASKPASS to point to the location of
+ * gnome-ssh-askpass before calling "ssh-add < /dev/null".
+ *
+ * There is only two run-time options: if you set the environment variable
+ * "GNOME_SSH_ASKPASS_GRAB_SERVER=true" then gnome-ssh-askpass will grab
+ * the X server. If you set "GNOME_SSH_ASKPASS_GRAB_POINTER=true", then the
+ * pointer will be grabbed too. These may have some benefit to security if
+ * you don't trust your X server. We grab the keyboard always.
+ */
+
+#define GRAB_TRIES 16
+#define GRAB_WAIT 250 /* milliseconds */
+
+#define PROMPT_ENTRY 0
+#define PROMPT_CONFIRM 1
+#define PROMPT_NONE 2
+
+/*
+ * Compile with:
+ *
+ * cc -Wall `pkg-config --cflags gtk+-2.0` \
+ * gnome-ssh-askpass2.c -o gnome-ssh-askpass \
+ * `pkg-config --libs gtk+-2.0`
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <X11/Xlib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkkeysyms.h>
+
+static void
+ok_dialog(GtkWidget *entry, gpointer dialog)
+{
+ g_return_if_fail(GTK_IS_DIALOG(dialog));
+ gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
+}
+
+static gboolean
+check_none(GtkWidget *widget, GdkEventKey *event, gpointer dialog)
+{
+ switch (event->keyval) {
+ case GDK_KEY_Escape:
+ /* esc -> close dialog */
+ gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE);
+ return TRUE;
+ case GDK_KEY_Tab:
+ /* tab -> focus close button */
+ gtk_widget_grab_focus(gtk_dialog_get_widget_for_response(
+ dialog, GTK_RESPONSE_CLOSE));
+ return TRUE;
+ default:
+ /* eat all other key events */
+ return TRUE;
+ }
+}
+
+static int
+parse_env_hex_color(const char *env, GdkColor *c)
+{
+ const char *s;
+ unsigned long ul;
+ char *ep;
+ size_t n;
+
+ if ((s = getenv(env)) == NULL)
+ return 0;
+
+ memset(c, 0, sizeof(*c));
+
+ /* Permit hex rgb or rrggbb optionally prefixed by '#' or '0x' */
+ if (*s == '#')
+ s++;
+ else if (strncmp(s, "0x", 2) == 0)
+ s += 2;
+ n = strlen(s);
+ if (n != 3 && n != 6)
+ goto bad;
+ ul = strtoul(s, &ep, 16);
+ if (*ep != '\0' || ul > 0xffffff) {
+ bad:
+ fprintf(stderr, "Invalid $%s - invalid hex color code\n", env);
+ return 0;
+ }
+ /* Valid hex sequence; expand into a GdkColor */
+ if (n == 3) {
+ /* 4-bit RGB */
+ c->red = ((ul >> 8) & 0xf) << 12;
+ c->green = ((ul >> 4) & 0xf) << 12;
+ c->blue = (ul & 0xf) << 12;
+ } else {
+ /* 8-bit RGB */
+ c->red = ((ul >> 16) & 0xff) << 8;
+ c->green = ((ul >> 8) & 0xff) << 8;
+ c->blue = (ul & 0xff) << 8;
+ }
+ return 1;
+}
+
+static int
+passphrase_dialog(char *message, int prompt_type)
+{
+ const char *failed;
+ char *passphrase, *local;
+ int result, grab_tries, grab_server, grab_pointer;
+ int buttons, default_response;
+ GtkWidget *parent_window, *dialog, *entry, *err;
+ GdkGrabStatus status;
+ GdkColor fg, bg;
+ GdkSeat *seat;
+ GdkDisplay *display;
+ GdkSeatCapabilities caps;
+ int fg_set = 0, bg_set = 0;
+
+ grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL);
+ grab_pointer = (getenv("GNOME_SSH_ASKPASS_GRAB_POINTER") != NULL);
+ grab_tries = 0;
+
+ fg_set = parse_env_hex_color("GNOME_SSH_ASKPASS_FG_COLOR", &fg);
+ bg_set = parse_env_hex_color("GNOME_SSH_ASKPASS_BG_COLOR", &bg);
+
+ /* Create an invisible parent window so that GtkDialog doesn't
+ * complain. */
+ parent_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+
+ switch (prompt_type) {
+ case PROMPT_CONFIRM:
+ buttons = GTK_BUTTONS_YES_NO;
+ default_response = GTK_RESPONSE_YES;
+ break;
+ case PROMPT_NONE:
+ buttons = GTK_BUTTONS_CLOSE;
+ default_response = GTK_RESPONSE_CLOSE;
+ break;
+ default:
+ buttons = GTK_BUTTONS_OK_CANCEL;
+ default_response = GTK_RESPONSE_OK;
+ break;
+ }
+
+ dialog = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0,
+ GTK_MESSAGE_QUESTION, buttons, "%s", message);
+
+ gtk_window_set_title(GTK_WINDOW(dialog), "OpenSSH");
+ gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
+ gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
+ gtk_dialog_set_default_response(GTK_DIALOG(dialog), default_response);
+ gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
+
+ if (fg_set)
+ gtk_widget_modify_fg(dialog, GTK_STATE_NORMAL, &fg);
+ if (bg_set)
+ gtk_widget_modify_bg(dialog, GTK_STATE_NORMAL, &bg);
+
+ if (prompt_type == PROMPT_ENTRY || prompt_type == PROMPT_NONE) {
+ entry = gtk_entry_new();
+ if (fg_set)
+ gtk_widget_modify_fg(entry, GTK_STATE_NORMAL, &fg);
+ if (bg_set)
+ gtk_widget_modify_bg(entry, GTK_STATE_NORMAL, &bg);
+ gtk_box_pack_start(
+ GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))),
+ entry, FALSE, FALSE, 0);
+ gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);
+ gtk_widget_grab_focus(entry);
+ if (prompt_type == PROMPT_ENTRY) {
+ gtk_widget_show(entry);
+ /* Make <enter> close dialog */
+ g_signal_connect(G_OBJECT(entry), "activate",
+ G_CALLBACK(ok_dialog), dialog);
+ } else {
+ /*
+ * Ensure the 'close' button is not focused by default
+ * but is still reachable via tab. This is a bit of a
+ * hack - it uses a hidden entry that responds to a
+ * couple of keypress events (escape and tab only).
+ */
+ gtk_widget_realize(entry);
+ g_signal_connect(G_OBJECT(entry), "key_press_event",
+ G_CALLBACK(check_none), dialog);
+ }
+ }
+ /* Grab focus */
+ gtk_widget_show_now(dialog);
+ display = gtk_widget_get_display(GTK_WIDGET(dialog));
+ seat = gdk_display_get_default_seat(display);
+ caps = GDK_SEAT_CAPABILITY_KEYBOARD;
+ if (grab_pointer)
+ caps |= GDK_SEAT_CAPABILITY_ALL_POINTING;
+ if (grab_server)
+ caps = GDK_SEAT_CAPABILITY_ALL;
+ for (;;) {
+ status = gdk_seat_grab(seat, gtk_widget_get_window(dialog),
+ caps, TRUE, NULL, NULL, NULL, NULL);
+ if (status == GDK_GRAB_SUCCESS)
+ break;
+ usleep(GRAB_WAIT * 1000);
+ if (++grab_tries > GRAB_TRIES)
+ goto nograb;
+ }
+
+ result = gtk_dialog_run(GTK_DIALOG(dialog));
+
+ /* Ungrab */
+ gdk_seat_ungrab(seat);
+ gdk_display_flush(display);
+
+ /* Report passphrase if user selected OK */
+ if (prompt_type == PROMPT_ENTRY) {
+ passphrase = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
+ if (result == GTK_RESPONSE_OK) {
+ local = g_locale_from_utf8(passphrase,
+ strlen(passphrase), NULL, NULL, NULL);
+ if (local != NULL) {
+ puts(local);
+ memset(local, '\0', strlen(local));
+ g_free(local);
+ } else {
+ puts(passphrase);
+ }
+ }
+ /* Zero passphrase in memory */
+ memset(passphrase, '\b', strlen(passphrase));
+ gtk_entry_set_text(GTK_ENTRY(entry), passphrase);
+ memset(passphrase, '\0', strlen(passphrase));
+ g_free(passphrase);
+ }
+
+ gtk_widget_destroy(dialog);
+ if (result != GTK_RESPONSE_OK && result != GTK_RESPONSE_YES)
+ return -1;
+ return 0;
+
+ nograb:
+ gtk_widget_destroy(dialog);
+ err = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
+ "Could not grab input. A malicious client may be eavesdropping "
+ "on your session.");
+ gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER);
+ gtk_dialog_run(GTK_DIALOG(err));
+ gtk_widget_destroy(err);
+ return -1;
+}
+
+int
+main(int argc, char **argv)
+{
+ char *message, *prompt_mode;
+ int result, prompt_type = PROMPT_ENTRY;
+
+ gtk_init(&argc, &argv);
+
+ if (argc > 1) {
+ message = g_strjoinv(" ", argv + 1);
+ } else {
+ message = g_strdup("Enter your OpenSSH passphrase:");
+ }
+
+ if ((prompt_mode = getenv("SSH_ASKPASS_PROMPT")) != NULL) {
+ if (strcasecmp(prompt_mode, "confirm") == 0)
+ prompt_type = PROMPT_CONFIRM;
+ else if (strcasecmp(prompt_mode, "none") == 0)
+ prompt_type = PROMPT_NONE;
+ }
+
+ setvbuf(stdout, 0, _IONBF, 0);
+ result = passphrase_dialog(message, prompt_type);
+ g_free(message);
+
+ return (result);
+}
diff --git a/contrib/redhat/openssh.spec b/contrib/redhat/openssh.spec
index dcd57aa19..2905db0e8 100644
--- a/contrib/redhat/openssh.spec
+++ b/contrib/redhat/openssh.spec
@@ -1,4 +1,4 @@
-%global ver 8.3p1
+%global ver 8.8p1
%global rel 1%{?dist}
# OpenSSH privilege separation requires a user & group ID
@@ -363,8 +363,10 @@ fi
%attr(0755,root,root) %dir %{_libexecdir}/openssh
%attr(4711,root,root) %{_libexecdir}/openssh/ssh-keysign
%attr(0755,root,root) %{_libexecdir}/openssh/ssh-pkcs11-helper
+%attr(0755,root,root) %{_libexecdir}/openssh/ssh-sk-helper
%attr(0644,root,root) %{_mandir}/man8/ssh-keysign.8*
%attr(0644,root,root) %{_mandir}/man8/ssh-pkcs11-helper.8*
+%attr(0644,root,root) %{_mandir}/man8/ssh-sk-helper.8*
%endif
%if %{scard}
%attr(0755,root,root) %dir %{_datadir}/openssh
@@ -422,6 +424,9 @@ fi
%endif
%changelog
+* Mon Jul 20 2020 Damien Miller <djm@mindrto.org>
+- Add ssh-sk-helper and corresponding manual page.
+
* Sat Feb 10 2018 Darren Tucker <dtucker@dtucker.net>
- Update openssl-devel dependency to match current requirements.
- Handle Fedora >=6 openssl 1.0 compat libs.
diff --git a/contrib/redhat/sshd.init.old b/contrib/redhat/sshd.init.old
deleted file mode 100755
index 8a30f7da4..000000000
--- a/contrib/redhat/sshd.init.old
+++ /dev/null
@@ -1,155 +0,0 @@
-#!/bin/bash
-#
-# Init file for OpenSSH server daemon
-#
-# chkconfig: 2345 55 25
-# description: OpenSSH server daemon
-#
-# processname: sshd
-# config: /etc/ssh/ssh_host_key
-# config: /etc/ssh/ssh_host_key.pub
-# config: /etc/ssh/ssh_random_seed
-# config: /etc/ssh/sshd_config
-# pidfile: /var/run/sshd.pid
-
-# source function library
-. /etc/rc.d/init.d/functions
-
-# pull in sysconfig settings
-[ -f /etc/sysconfig/sshd ] && . /etc/sysconfig/sshd
-
-RETVAL=0
-prog="sshd"
-
-# Some functions to make the below more readable
-KEYGEN=/usr/bin/ssh-keygen
-SSHD=/usr/sbin/sshd
-RSA_KEY=/etc/ssh/ssh_host_rsa_key
-DSA_KEY=/etc/ssh/ssh_host_dsa_key
-PID_FILE=/var/run/sshd.pid
-
-my_success() {
- local msg
- if [ $# -gt 1 ]; then
- msg="$2"
- else
- msg="done"
- fi
- case "`type -type success`" in
- function)
- success "$1"
- ;;
- *)
- echo -n "${msg}"
- ;;
- esac
-}
-my_failure() {
- local msg
- if [ $# -gt 1 ]; then
- msg="$2"
- else
- msg="FAILED"
- fi
- case "`type -type failure`" in
- function)
- failure "$1"
- ;;
- *)
- echo -n "${msg}"
- ;;
- esac
-}
-do_rsa_keygen() {
- if [ ! -s $RSA_KEY ]; then
- echo -n "Generating SSH2 RSA host key: "
- if $KEYGEN -q -t rsa -f $RSA_KEY -C '' -N '' >&/dev/null; then
- chmod 600 $RSA_KEY
- chmod 644 $RSA_KEY.pub
- my_success "RSA key generation"
- echo
- else
- my_failure "RSA key generation"
- echo
- exit 1
- fi
- fi
-}
-do_dsa_keygen() {
- if [ ! -s $DSA_KEY ]; then
- echo -n "Generating SSH2 DSA host key: "
- if $KEYGEN -q -t dsa -f $DSA_KEY -C '' -N '' >&/dev/null; then
- chmod 600 $DSA_KEY
- chmod 644 $DSA_KEY.pub
- my_success "DSA key generation"
- echo
- else
- my_failure "DSA key generation"
- echo
- exit 1
- fi
- fi
-}
-do_restart_sanity_check() {
- $SSHD -t
- RETVAL=$?
- if [ ! "$RETVAL" = 0 ]; then
- my_failure "Configuration file or keys"
- echo
- fi
-}
-
-
-case "$1" in
- start)
- # Create keys if necessary
- do_rsa_keygen;
- do_dsa_keygen;
-
- echo -n "Starting sshd: "
- if [ ! -f $PID_FILE ] ; then
- sshd $OPTIONS
- RETVAL=$?
- if [ "$RETVAL" = "0" ] ; then
- my_success "sshd startup" "sshd"
- touch /var/lock/subsys/sshd
- else
- my_failure "sshd startup" ""
- fi
- fi
- echo
- ;;
- stop)
- echo -n "Shutting down sshd: "
- if [ -f $PID_FILE ] ; then
- killproc sshd
- RETVAL=$?
- [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/sshd
- fi
- echo
- ;;
- restart)
- do_restart_sanity_check
- $0 stop
- $0 start
- RETVAL=$?
- ;;
- condrestart)
- if [ -f /var/lock/subsys/sshd ] ; then
- do_restart_sanity_check
- $0 stop
- $0 start
- RETVAL=$?
- fi
- ;;
- status)
- status sshd
- RETVAL=$?
- ;;
- *)
- echo "Usage: sshd {start|stop|restart|status|condrestart}"
- exit 1
- ;;
-esac
-
-exit $RETVAL
diff --git a/contrib/redhat/sshd.pam.old b/contrib/redhat/sshd.pam.old
deleted file mode 100644
index 26dcb34d9..000000000
--- a/contrib/redhat/sshd.pam.old
+++ /dev/null
@@ -1,8 +0,0 @@
-#%PAM-1.0
-auth required /lib/security/pam_pwdb.so shadow nodelay
-auth required /lib/security/pam_nologin.so
-account required /lib/security/pam_pwdb.so
-password required /lib/security/pam_cracklib.so
-password required /lib/security/pam_pwdb.so shadow nullok use_authtok
-session required /lib/security/pam_pwdb.so
-session required /lib/security/pam_limits.so
diff --git a/contrib/ssh-copy-id b/contrib/ssh-copy-id
index b83b83619..cd122def3 100644
--- a/contrib/ssh-copy-id
+++ b/contrib/ssh-copy-id
@@ -1,6 +1,8 @@
#!/bin/sh
-# Copyright (c) 1999-2016 Philip Hands <phil@hands.com>
+# Copyright (c) 1999-2020 Philip Hands <phil@hands.com>
+# 2020 Matthias Blümel <blaimi@blaimi.de>
+# 2017 Sebastien Boyron <seb@boyron.eu>
# 2013 Martin Kletzander <mkletzan@redhat.com>
# 2010 Adeodato =?iso-8859-1?Q?Sim=F3?= <asp16@alu.ua.es>
# 2010 Eric Moret <eric.moret@gmail.com>
@@ -33,13 +35,15 @@
# Shell script to install your public key(s) on a remote machine
# See the ssh-copy-id(1) man page for details
+# shellcheck shell=dash
+
# check that we have something mildly sane as our shell, or try to find something better
if false ^ printf "%s: WARNING: ancient shell, hunting for a more modern one... " "$0"
then
SANE_SH=${SANE_SH:-/usr/bin/ksh}
if printf 'true ^ false\n' | "$SANE_SH"
then
- printf "'%s' seems viable.\n" "$SANE_SH"
+ printf "'%s' seems viable.\\n" "$SANE_SH"
exec "$SANE_SH" "$0" "$@"
else
cat <<-EOF
@@ -51,36 +55,39 @@ then
a bug describing your setup, and the shell you used to make it work.
EOF
- printf "%s: ERROR: Less dimwitted shell required.\n" "$0"
+ printf '%s: ERROR: Less dimwitted shell required.\n' "$0"
exit 1
fi
fi
-most_recent_id="$(cd "$HOME" ; ls -t .ssh/id*.pub 2>/dev/null | grep -v -- '-cert.pub$' | head -n 1)"
-DEFAULT_PUB_ID_FILE="${most_recent_id:+$HOME/}$most_recent_id"
+# shellcheck disable=SC2010
+DEFAULT_PUB_ID_FILE=$(ls -t "${HOME}"/.ssh/id*.pub 2>/dev/null | grep -v -- '-cert.pub$' | head -n 1)
+SSH="ssh -a -x"
+umask 0177
usage () {
- printf 'Usage: %s [-h|-?|-f|-n] [-i [identity_file]] [-p port] [[-o <ssh -o options>] ...] [user@]hostname\n' "$0" >&2
+ printf 'Usage: %s [-h|-?|-f|-n|-s] [-i [identity_file]] [-p port] [-F alternative ssh_config file] [[-o <ssh -o options>] ...] [user@]hostname\n' "$0" >&2
printf '\t-f: force mode -- copy keys without trying to check if they are already installed\n' >&2
printf '\t-n: dry run -- no keys are actually copied\n' >&2
+ printf '\t-s: use sftp -- use sftp instead of executing remote-commands. Can be useful if the remote only allows sftp\n' >&2
printf '\t-h|-?: print this help\n' >&2
exit 1
}
# escape any single quotes in an argument
quote() {
- printf "%s\n" "$1" | sed -e "s/'/'\\\\''/g"
+ printf '%s\n' "$1" | sed -e "s/'/'\\\\''/g"
}
use_id_file() {
- local L_ID_FILE="$1"
+ L_ID_FILE="$1"
if [ -z "$L_ID_FILE" ] ; then
- printf "%s: ERROR: no ID file found\n" "$0"
+ printf '%s: ERROR: no ID file found\n' "$0"
exit 1
fi
- if expr "$L_ID_FILE" : ".*\.pub$" >/dev/null ; then
+ if expr "$L_ID_FILE" : '.*\.pub$' >/dev/null ; then
PUB_ID_FILE="$L_ID_FILE"
else
PUB_ID_FILE="$L_ID_FILE.pub"
@@ -91,9 +98,9 @@ use_id_file() {
# check that the files are readable
for f in "$PUB_ID_FILE" ${PRIV_ID_FILE:+"$PRIV_ID_FILE"} ; do
ErrMSG=$( { : < "$f" ; } 2>&1 ) || {
- local L_PRIVMSG=""
+ L_PRIVMSG=""
[ "$f" = "$PRIV_ID_FILE" ] && L_PRIVMSG=" (to install the contents of '$PUB_ID_FILE' anyway, look at the -f option)"
- printf "\n%s: ERROR: failed to open ID file '%s': %s\n" "$0" "$f" "$(printf "%s\n%s\n" "$ErrMSG" "$L_PRIVMSG" | sed -e 's/.*: *//')"
+ printf "\\n%s: ERROR: failed to open ID file '%s': %s\\n" "$0" "$f" "$(printf '%s\n%s\n' "$ErrMSG" "$L_PRIVMSG" | sed -e 's/.*: *//')"
exit 1
}
done
@@ -105,80 +112,36 @@ if [ -n "$SSH_AUTH_SOCK" ] && ssh-add -L >/dev/null 2>&1 ; then
GET_ID="ssh-add -L"
fi
-while test "$#" -gt 0
+while getopts "i:o:p:F:fnsh?" OPT
do
- [ "${SEEN_OPT_I}" ] && expr "$1" : "[-]i" >/dev/null && {
- printf "\n%s: ERROR: -i option must not be specified more than once\n\n" "$0"
+ case "$OPT" in
+ i)
+ [ "${SEEN_OPT_I}" ] && {
+ printf '\n%s: ERROR: -i option must not be specified more than once\n\n' "$0"
usage
- }
-
- OPT= OPTARG=
- # implement something like getopt to avoid Solaris pain
- case "$1" in
- -i?*|-o?*|-p?*)
- OPT="$(printf -- "$1"|cut -c1-2)"
- OPTARG="$(printf -- "$1"|cut -c3-)"
- shift
- ;;
- -o|-p)
- OPT="$1"
- OPTARG="$2"
- shift 2
- ;;
- -i)
- OPT="$1"
- test "$#" -le 2 || expr "$2" : "[-]" >/dev/null || {
- OPTARG="$2"
- shift
}
- shift
- ;;
- -f|-n|-h|-\?)
- OPT="$1"
- OPTARG=
- shift
- ;;
- --)
- shift
- while test "$#" -gt 0
- do
- SAVEARGS="${SAVEARGS:+$SAVEARGS }'$(quote "$1")'"
- shift
- done
- break
- ;;
- -*)
- printf "\n%s: ERROR: invalid option (%s)\n\n" "$0" "$1"
- usage
- ;;
- *)
- SAVEARGS="${SAVEARGS:+$SAVEARGS }'$(quote "$1")'"
- shift
- continue
- ;;
- esac
-
- case "$OPT" in
- -i)
SEEN_OPT_I="yes"
use_id_file "${OPTARG:-$DEFAULT_PUB_ID_FILE}"
;;
- -o|-p)
- SSH_OPTS="${SSH_OPTS:+$SSH_OPTS }$OPT '$(quote "$OPTARG")'"
+ o|p|F)
+ SSH_OPTS="${SSH_OPTS:+$SSH_OPTS }-$OPT '$(quote "${OPTARG}")'"
;;
- -f)
+ f)
FORCED=1
;;
- -n)
+ n)
DRY_RUN=1
;;
- -h|-\?)
+ s)
+ SFTP=sftp
+ ;;
+ h|\?)
usage
;;
esac
done
-
-eval set -- "$SAVEARGS"
+#shift all args to keep only USER_HOST
+shift $((OPTIND-1))
if [ $# = 0 ] ; then
usage
@@ -189,71 +152,74 @@ if [ $# != 1 ] ; then
fi
# drop trailing colon
-USER_HOST=$(printf "%s\n" "$1" | sed 's/:$//')
+USER_HOST="$*"
# tack the hostname onto SSH_OPTS
SSH_OPTS="${SSH_OPTS:+$SSH_OPTS }'$(quote "$USER_HOST")'"
# and populate "$@" for later use (only way to get proper quoting of options)
eval set -- "$SSH_OPTS"
+# shellcheck disable=SC2086
if [ -z "$(eval $GET_ID)" ] && [ -r "${PUB_ID_FILE:=$DEFAULT_PUB_ID_FILE}" ] ; then
use_id_file "$PUB_ID_FILE"
fi
+# shellcheck disable=SC2086
if [ -z "$(eval $GET_ID)" ] ; then
printf '%s: ERROR: No identities found\n' "$0" >&2
exit 1
fi
+# filter_ids()
+# tries to log in using the keys piped to it, and filters out any that work
+filter_ids() {
+ L_SUCCESS="$1"
+ L_TMP_ID_FILE="$SCRATCH_DIR"/popids_tmp_id
+ L_OUTPUT_FILE="$SCRATCH_DIR"/popids_output
+
+ # repopulate "$@" inside this function
+ eval set -- "$SSH_OPTS"
+
+ while read -r ID || [ "$ID" ] ; do
+ printf '%s\n' "$ID" > "$L_TMP_ID_FILE"
+
+ # the next line assumes $PRIV_ID_FILE only set if using a single id file - this
+ # assumption will break if we implement the possibility of multiple -i options.
+ # The point being that if file based, ssh needs the private key, which it cannot
+ # find if only given the contents of the .pub file in an unrelated tmpfile
+ $SSH -i "${PRIV_ID_FILE:-$L_TMP_ID_FILE}" \
+ -o ControlPath=none \
+ -o LogLevel=INFO \
+ -o PreferredAuthentications=publickey \
+ -o IdentitiesOnly=yes "$@" exit >"$L_OUTPUT_FILE" 2>&1 </dev/null
+ if [ "$?" = "$L_SUCCESS" ] || {
+ [ "$SFTP" ] && grep 'allows sftp connections only' "$L_OUTPUT_FILE" >/dev/null
+ # this error counts as a success if we're setting up an sftp connection
+ }
+ then
+ : > "$L_TMP_ID_FILE"
+ else
+ grep 'Permission denied' "$L_OUTPUT_FILE" >/dev/null || {
+ sed -e 's/^/ERROR: /' <"$L_OUTPUT_FILE" >"$L_TMP_ID_FILE"
+ cat >/dev/null #consume the other keys, causing loop to end
+ }
+ fi
+
+ cat "$L_TMP_ID_FILE"
+ done
+}
+
# populate_new_ids() uses several global variables ($USER_HOST, $SSH_OPTS ...)
# and has the side effect of setting $NEW_IDS
populate_new_ids() {
- local L_SUCCESS="$1"
-
if [ "$FORCED" ] ; then
+ # shellcheck disable=SC2086
NEW_IDS=$(eval $GET_ID)
return
fi
- # repopulate "$@" inside this function
- eval set -- "$SSH_OPTS"
-
- umask 0177
- local L_TMP_ID_FILE=$(mktemp ~/.ssh/ssh-copy-id_id.XXXXXXXXXX)
- if test $? -ne 0 || test "x$L_TMP_ID_FILE" = "x" ; then
- printf '%s: ERROR: mktemp failed\n' "$0" >&2
- exit 1
- fi
- local L_CLEANUP="rm -f \"$L_TMP_ID_FILE\" \"${L_TMP_ID_FILE}.stderr\""
- trap "$L_CLEANUP" EXIT TERM INT QUIT
printf '%s: INFO: attempting to log in with the new key(s), to filter out any that are already installed\n' "$0" >&2
- NEW_IDS=$(
- eval $GET_ID | {
- while read ID || [ "$ID" ] ; do
- printf '%s\n' "$ID" > "$L_TMP_ID_FILE"
-
- # the next line assumes $PRIV_ID_FILE only set if using a single id file - this
- # assumption will break if we implement the possibility of multiple -i options.
- # The point being that if file based, ssh needs the private key, which it cannot
- # find if only given the contents of the .pub file in an unrelated tmpfile
- ssh -i "${PRIV_ID_FILE:-$L_TMP_ID_FILE}" \
- -o ControlPath=none \
- -o LogLevel=INFO \
- -o PreferredAuthentications=publickey \
- -o IdentitiesOnly=yes "$@" exit 2>"$L_TMP_ID_FILE.stderr" </dev/null
- if [ "$?" = "$L_SUCCESS" ] ; then
- : > "$L_TMP_ID_FILE"
- else
- grep 'Permission denied' "$L_TMP_ID_FILE.stderr" >/dev/null || {
- sed -e 's/^/ERROR: /' <"$L_TMP_ID_FILE.stderr" >"$L_TMP_ID_FILE"
- cat >/dev/null #consume the other keys, causing loop to end
- }
- fi
-
- cat "$L_TMP_ID_FILE"
- done
- }
- )
- eval "$L_CLEANUP" && trap - EXIT TERM INT QUIT
+ # shellcheck disable=SC2086
+ NEW_IDS=$(eval $GET_ID | filter_ids $1)
if expr "$NEW_IDS" : "^ERROR: " >/dev/null ; then
printf '\n%s: %s\n\n' "$0" "$NEW_IDS" >&2
@@ -261,45 +227,132 @@ populate_new_ids() {
fi
if [ -z "$NEW_IDS" ] ; then
printf '\n%s: WARNING: All keys were skipped because they already exist on the remote system.\n' "$0" >&2
- printf '\t\t(if you think this is a mistake, you may want to use -f option)\n\n' "$0" >&2
+ printf '\t\t(if you think this is a mistake, you may want to use -f option)\n\n' >&2
exit 0
fi
printf '%s: INFO: %d key(s) remain to be installed -- if you are prompted now it is to install the new keys\n' "$0" "$(printf '%s\n' "$NEW_IDS" | wc -l)" >&2
}
-REMOTE_VERSION=$(ssh -v -o PreferredAuthentications=',' -o ControlPath=none "$@" 2>&1 |
+# installkey_sh [target_path]
+# produce a one-liner to add the keys to remote authorized_keys file
+# optionally takes an alternative path for authorized_keys
+installkeys_sh() {
+ AUTH_KEY_FILE=${1:-.ssh/authorized_keys}
+ AUTH_KEY_DIR=$(dirname "${AUTH_KEY_FILE}")
+
+ # In setting INSTALLKEYS_SH:
+ # the tr puts it all on one line (to placate tcsh)
+ # (hence the excessive use of semi-colons (;) )
+ # then in the command:
+ # cd to be at $HOME, just in case;
+ # the -z `tail ...` checks for a trailing newline. The echo adds one if was missing
+ # the cat adds the keys we're getting via STDIN
+ # and if available restorecon is used to restore the SELinux context
+ INSTALLKEYS_SH=$(tr '\t\n' ' ' <<-EOF
+ cd;
+ umask 077;
+ mkdir -p "${AUTH_KEY_DIR}" &&
+ { [ -z \`tail -1c ${AUTH_KEY_FILE} 2>/dev/null\` ] ||
+ echo >> "${AUTH_KEY_FILE}" || exit 1; } &&
+ cat >> "${AUTH_KEY_FILE}" || exit 1;
+ if type restorecon >/dev/null 2>&1; then
+ restorecon -F "${AUTH_KEY_DIR}" "${AUTH_KEY_FILE}";
+ fi
+ EOF
+ )
+
+ # to defend against quirky remote shells: use 'exec sh -c' to get POSIX;
+ printf "exec sh -c '%s'" "${INSTALLKEYS_SH}"
+}
+
+#shellcheck disable=SC2120 # the 'eval set' confuses this
+installkeys_via_sftp() {
+
+ # repopulate "$@" inside this function
+ eval set -- "$SSH_OPTS"
+
+ L_KEYS=$SCRATCH_DIR/authorized_keys
+ L_SHARED_CON=$SCRATCH_DIR/master-conn
+ $SSH -f -N -M -S "$L_SHARED_CON" "$@"
+ L_CLEANUP="$SSH -S $L_SHARED_CON -O exit 'ignored' >/dev/null 2>&1 ; $SCRATCH_CLEANUP"
+ #shellcheck disable=SC2064
+ trap "$L_CLEANUP" EXIT TERM INT QUIT
+ sftp -b - -o "ControlPath=$L_SHARED_CON" "ignored" <<-EOF || return 1
+ -get .ssh/authorized_keys $L_KEYS
+ EOF
+ # add a newline or create file if it's missing, same like above
+ [ -z "$(tail -1c "$L_KEYS" 2>/dev/null)" ] || echo >> "$L_KEYS"
+ # append the keys being piped in here
+ cat >> "$L_KEYS"
+ sftp -b - -o "ControlPath=$L_SHARED_CON" "ignored" <<-EOF || return 1
+ -mkdir .ssh
+ chmod 700 .ssh
+ put $L_KEYS .ssh/authorized_keys
+ chmod 600 .ssh/authorized_keys
+ EOF
+ #shellcheck disable=SC2064
+ eval "$L_CLEANUP" && trap "$SCRATCH_CLEANUP" EXIT TERM INT QUIT
+}
+
+
+# create a scratch dir for any temporary files needed
+if SCRATCH_DIR=$(mktemp -d ~/.ssh/ssh-copy-id.XXXXXXXXXX) &&
+ [ "$SCRATCH_DIR" ] && [ -d "$SCRATCH_DIR" ]
+then
+ chmod 0700 "$SCRATCH_DIR"
+ SCRATCH_CLEANUP="rm -rf \"$SCRATCH_DIR\""
+ #shellcheck disable=SC2064
+ trap "$SCRATCH_CLEANUP" EXIT TERM INT QUIT
+else
+ printf '%s: ERROR: failed to create required temporary directory under ~/.ssh\n' "$0" >&2
+ exit 1
+fi
+
+REMOTE_VERSION=$($SSH -v -o PreferredAuthentications=',' -o ControlPath=none "$@" 2>&1 |
sed -ne 's/.*remote software version //p')
+# shellcheck disable=SC2029
case "$REMOTE_VERSION" in
NetScreen*)
populate_new_ids 1
for KEY in $(printf "%s" "$NEW_IDS" | cut -d' ' -f2) ; do
- KEY_NO=$(($KEY_NO + 1))
- printf "%s\n" "$KEY" | grep ssh-dss >/dev/null || {
+ KEY_NO=$((KEY_NO + 1))
+ printf '%s\n' "$KEY" | grep ssh-dss >/dev/null || {
printf '%s: WARNING: Non-dsa key (#%d) skipped (NetScreen only supports DSA keys)\n' "$0" "$KEY_NO" >&2
continue
}
- [ "$DRY_RUN" ] || printf 'set ssh pka-dsa key %s\nsave\nexit\n' "$KEY" | ssh -T "$@" >/dev/null 2>&1
+ [ "$DRY_RUN" ] || printf 'set ssh pka-dsa key %s\nsave\nexit\n' "$KEY" | $SSH -T "$@" >/dev/null 2>&1
if [ $? = 255 ] ; then
printf '%s: ERROR: installation of key #%d failed (please report a bug describing what caused this, so that we can make this message useful)\n' "$0" "$KEY_NO" >&2
else
- ADDED=$(($ADDED + 1))
+ ADDED=$((ADDED + 1))
fi
done
if [ -z "$ADDED" ] ; then
exit 1
fi
;;
- *)
- # Assuming that the remote host treats ~/.ssh/authorized_keys as one might expect
+ dropbear*)
populate_new_ids 0
- # in ssh below - to defend against quirky remote shells: use 'exec sh -c' to get POSIX;
- # 'cd' to be at $HOME; add a newline if it's missing; and all on one line, because tcsh.
[ "$DRY_RUN" ] || printf '%s\n' "$NEW_IDS" | \
- ssh "$@" "exec sh -c 'cd ; umask 077 ; mkdir -p .ssh && { [ -z "'`tail -1c .ssh/authorized_keys 2>/dev/null`'" ] || echo >> .ssh/authorized_keys ; } && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi'" \
+ $SSH "$@" "$(installkeys_sh /etc/dropbear/authorized_keys)" \
|| exit 1
ADDED=$(printf '%s\n' "$NEW_IDS" | wc -l)
;;
+ *)
+ # Assuming that the remote host treats ~/.ssh/authorized_keys as one might expect
+ populate_new_ids 0
+ if ! [ "$DRY_RUN" ] ; then
+ printf '%s\n' "$NEW_IDS" | \
+ if [ "$SFTP" ] ; then
+ #shellcheck disable=SC2119
+ installkeys_via_sftp
+ else
+ $SSH "$@" "$(installkeys_sh)"
+ fi || exit 1
+ fi
+ ADDED=$(printf '%s\n' "$NEW_IDS" | wc -l)
+ ;;
esac
if [ "$DRY_RUN" ] ; then
@@ -315,7 +368,7 @@ else
Number of key(s) added: $ADDED
- Now try logging into the machine, with: "ssh $SSH_OPTS"
+ Now try logging into the machine, with: "${SFTP:-ssh} $SSH_OPTS"
and check to make sure that only the key(s) you wanted were added.
EOF
diff --git a/contrib/ssh-copy-id.1 b/contrib/ssh-copy-id.1
index ae75c79a5..c141a296f 100644
--- a/contrib/ssh-copy-id.1
+++ b/contrib/ssh-copy-id.1
@@ -1,5 +1,5 @@
.ig \" -*- nroff -*-
-Copyright (c) 1999-2013 hands.com Ltd. <http://hands.com/>
+Copyright (c) 1999-2020 hands.com Ltd. <http://hands.com/>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -31,6 +31,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.Nm
.Op Fl f
.Op Fl n
+.Op Fl s
.Op Fl i Op Ar identity_file
.Op Fl p Ar port
.Op Fl o Ar ssh_option
@@ -84,6 +85,12 @@ in more than one copy of the key being installed on the remote system.
.It Fl n
do a dry-run. Instead of installing keys on the remote system simply
prints the key(s) that would have been installed.
+.It Fl s
+SFTP mode: usually the public keys are installed by executing commands on the remote side.
+With this option the user's
+.Pa ~/.ssh/authorized_keys
+file will be downloaded, modified locally and uploaded with sftp.
+This option is useful if the server has restrictions on commands which can be used on the remote side.
.It Fl h , Fl ?
Print Usage summary
.It Fl p Ar port , Fl o Ar ssh_option
diff --git a/contrib/suse/openssh.spec b/contrib/suse/openssh.spec
index a2789052d..ee320c76d 100644
--- a/contrib/suse/openssh.spec
+++ b/contrib/suse/openssh.spec
@@ -13,7 +13,7 @@
Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation
Name: openssh
-Version: 8.3p1
+Version: 8.8p1
URL: https://www.openssh.com/
Release: 1
Source0: openssh-%{version}.tar.gz
@@ -75,6 +75,8 @@ patented algorithms to separate libraries (OpenSSL).
This package contains an X Window System passphrase dialog for OpenSSH.
%changelog
+* Mon Jul 20 2020 Damien Miller <djm@mindrto.org>
+- Add ssh-sk-helper and corresponding manual page.
* Wed Oct 26 2005 Iain Morgan <imorgan@nas.nasa.gov>
- Removed accidental inclusion of --without-zlib-version-check
* Tue Oct 25 2005 Iain Morgan <imorgan@nas.nasa.gov>
@@ -211,6 +213,7 @@ rm -rf $RPM_BUILD_ROOT
%attr(0755,root,root) %{_libdir}/ssh/sftp-server
%attr(4711,root,root) %{_libdir}/ssh/ssh-keysign
%attr(0755,root,root) %{_libdir}/ssh/ssh-pkcs11-helper
+%attr(0755,root,root) %{_libdir}/ssh/ssh-sk-helper
%attr(0644,root,root) %doc %{_mandir}/man1/scp.1*
%attr(0644,root,root) %doc %{_mandir}/man1/sftp.1*
%attr(0644,root,root) %doc %{_mandir}/man1/ssh.1*
@@ -224,6 +227,7 @@ rm -rf $RPM_BUILD_ROOT
%attr(0644,root,root) %doc %{_mandir}/man8/sftp-server.8*
%attr(0644,root,root) %doc %{_mandir}/man8/ssh-keysign.8*
%attr(0644,root,root) %doc %{_mandir}/man8/ssh-pkcs11-helper.8*
+%attr(0644,root,root) %doc %{_mandir}/man8/ssh-sk-helper.8*
%attr(0644,root,root) %doc %{_mandir}/man8/sshd.8*
%attr(0644,root,root) /var/adm/fillup-templates/sysconfig.ssh
diff --git a/crypto_api.h b/crypto_api.h
index eb05251ff..5c3d97eaa 100644
--- a/crypto_api.h
+++ b/crypto_api.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: crypto_api.h,v 1.5 2019/01/21 10:20:12 djm Exp $ */
+/* $OpenBSD: crypto_api.h,v 1.7 2021/01/08 02:33:13 dtucker Exp $ */
/*
* Assembled from generated headers and source files by Markus Friedl.
@@ -21,6 +21,8 @@ typedef int16_t crypto_int16;
typedef uint16_t crypto_uint16;
typedef int32_t crypto_int32;
typedef uint32_t crypto_uint32;
+typedef int64_t crypto_int64;
+typedef uint64_t crypto_uint64;
#define randombytes(buf, buf_len) arc4random_buf((buf), (buf_len))
#define small_random32() arc4random()
@@ -42,15 +44,15 @@ int crypto_sign_ed25519_open(unsigned char *, unsigned long long *,
const unsigned char *, unsigned long long, const unsigned char *);
int crypto_sign_ed25519_keypair(unsigned char *, unsigned char *);
-#define crypto_kem_sntrup4591761_PUBLICKEYBYTES 1218
-#define crypto_kem_sntrup4591761_SECRETKEYBYTES 1600
-#define crypto_kem_sntrup4591761_CIPHERTEXTBYTES 1047
-#define crypto_kem_sntrup4591761_BYTES 32
+#define crypto_kem_sntrup761_PUBLICKEYBYTES 1158
+#define crypto_kem_sntrup761_SECRETKEYBYTES 1763
+#define crypto_kem_sntrup761_CIPHERTEXTBYTES 1039
+#define crypto_kem_sntrup761_BYTES 32
-int crypto_kem_sntrup4591761_enc(unsigned char *cstr, unsigned char *k,
+int crypto_kem_sntrup761_enc(unsigned char *cstr, unsigned char *k,
const unsigned char *pk);
-int crypto_kem_sntrup4591761_dec(unsigned char *k,
+int crypto_kem_sntrup761_dec(unsigned char *k,
const unsigned char *cstr, const unsigned char *sk);
-int crypto_kem_sntrup4591761_keypair(unsigned char *pk, unsigned char *sk);
+int crypto_kem_sntrup761_keypair(unsigned char *pk, unsigned char *sk);
#endif /* crypto_api_h */
diff --git a/defines.h b/defines.h
index b8ea88b2d..857abb8b1 100644
--- a/defines.h
+++ b/defines.h
@@ -304,6 +304,12 @@ typedef long long intmax_t;
typedef unsigned long long uintmax_t;
#endif
+#if SIZEOF_TIME_T == SIZEOF_LONG_LONG_INT
+# define SSH_TIME_T_MAX LLONG_MAX
+#else
+# define SSH_TIME_T_MAX INT_MAX
+#endif
+
#ifndef HAVE_U_CHAR
typedef unsigned char u_char;
# define HAVE_U_CHAR
@@ -829,10 +835,6 @@ struct winsize {
# define getgroups(a,b) ((a)==0 && (b)==NULL ? NGROUPS_MAX : getgroups((a),(b)))
#endif
-#if defined(HAVE_MMAP) && defined(BROKEN_MMAP)
-# undef HAVE_MMAP
-#endif
-
#ifndef IOV_MAX
# if defined(_XOPEN_IOV_MAX)
# define IOV_MAX _XOPEN_IOV_MAX
@@ -898,4 +900,11 @@ struct winsize {
# define USE_SYSTEM_GLOB
#endif
+/*
+ * sntrup761 uses variable length arrays and c99-style declarations after code,
+ * so only enable if the compiler supports them.
+ */
+#if defined(VARIABLE_LENGTH_ARRAYS) && defined(VARIABLE_DECLARATION_AFTER_CODE)
+# define USE_SNTRUP761X25519 1
+#endif
#endif /* _DEFINES_H */
diff --git a/dh.c b/dh.c
index 7cb135d7d..ce2eb4725 100644
--- a/dh.c
+++ b/dh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dh.c,v 1.71 2019/09/06 06:08:11 djm Exp $ */
+/* $OpenBSD: dh.c,v 1.74 2021/04/03 06:18:40 djm Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
*
@@ -45,6 +45,18 @@
#include "openbsd-compat/openssl-compat.h"
+static const char *moduli_filename;
+
+void dh_set_moduli_file(const char *filename)
+{
+ moduli_filename = filename;
+}
+
+static const char * get_moduli_filename(void)
+{
+ return moduli_filename ? moduli_filename : _PATH_DH_MODULI;
+}
+
static int
parse_prime(int linenum, char *line, struct dhgroup *dhg)
{
@@ -152,9 +164,9 @@ choose_dh(int min, int wantbits, int max)
int best, bestcount, which, linenum;
struct dhgroup dhg;
- if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL) {
+ if ((f = fopen(get_moduli_filename(), "r")) == NULL) {
logit("WARNING: could not open %s (%s), using fixed modulus",
- _PATH_DH_MODULI, strerror(errno));
+ get_moduli_filename(), strerror(errno));
return (dh_new_group_fallback(max));
}
@@ -185,7 +197,8 @@ choose_dh(int min, int wantbits, int max)
if (bestcount == 0) {
fclose(f);
- logit("WARNING: no suitable primes in %s", _PATH_DH_MODULI);
+ logit("WARNING: no suitable primes in %s",
+ get_moduli_filename());
return (dh_new_group_fallback(max));
}
which = arc4random_uniform(bestcount);
@@ -210,7 +223,7 @@ choose_dh(int min, int wantbits, int max)
fclose(f);
if (bestcount != which + 1) {
logit("WARNING: selected prime disappeared in %s, giving up",
- _PATH_DH_MODULI);
+ get_moduli_filename());
return (dh_new_group_fallback(max));
}
@@ -240,7 +253,7 @@ dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub)
}
if ((tmp = BN_new()) == NULL) {
- error("%s: BN_new failed", __func__);
+ error_f("BN_new failed");
return 0;
}
if (!BN_sub(tmp, dh_p, BN_value_one()) ||
@@ -261,7 +274,7 @@ dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub)
*/
if (bits_set < 4) {
logit("invalid public DH value (%d/%d)",
- bits_set, BN_num_bits(dh_p));
+ bits_set, BN_num_bits(dh_p));
return 0;
}
return 1;
@@ -458,7 +471,7 @@ dh_new_group18(void)
DH *
dh_new_group_fallback(int max)
{
- debug3("%s: requested max size %d", __func__, max);
+ debug3_f("requested max size %d", max);
if (max < 3072) {
debug3("using 2k bit group 14");
return dh_new_group14();
diff --git a/dh.h b/dh.h
index 5d6df6297..c6326a39d 100644
--- a/dh.h
+++ b/dh.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dh.h,v 1.18 2019/09/06 05:23:55 djm Exp $ */
+/* $OpenBSD: dh.h,v 1.19 2021/03/12 04:08:19 dtucker Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
@@ -47,6 +47,7 @@ int dh_gen_key(DH *, int);
int dh_pub_is_valid(const DH *, const BIGNUM *);
u_int dh_estimate(int);
+void dh_set_moduli_file(const char *);
/*
* Max value from RFC4419.
diff --git a/digest-openssl.c b/digest-openssl.c
index dbbea4251..e073a807b 100644
--- a/digest-openssl.c
+++ b/digest-openssl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: digest-openssl.c,v 1.7 2017/05/08 22:57:38 djm Exp $ */
+/* $OpenBSD: digest-openssl.c,v 1.9 2020/10/29 02:52:43 djm Exp $ */
/*
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
*
@@ -56,11 +56,11 @@ struct ssh_digest {
/* NB. Indexed directly by algorithm number */
const struct ssh_digest digests[] = {
- { SSH_DIGEST_MD5, "MD5", 16, EVP_md5 },
- { SSH_DIGEST_SHA1, "SHA1", 20, EVP_sha1 },
- { SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 },
+ { SSH_DIGEST_MD5, "MD5", 16, EVP_md5 },
+ { SSH_DIGEST_SHA1, "SHA1", 20, EVP_sha1 },
+ { SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 },
{ SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 },
- { SSH_DIGEST_SHA512, "SHA512", 64, EVP_sha512 },
+ { SSH_DIGEST_SHA512, "SHA512", 64, EVP_sha512 },
{ -1, NULL, 0, NULL },
};
diff --git a/dns.c b/dns.c
index cb375c85e..5a078d1d1 100644
--- a/dns.c
+++ b/dns.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dns.c,v 1.38 2018/02/23 15:58:37 markus Exp $ */
+/* $OpenBSD: dns.c,v 1.41 2021/07/19 03:13:28 dtucker Exp $ */
/*
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
@@ -75,6 +75,7 @@ dns_result_totext(unsigned int res)
/*
* Read SSHFP parameters from key buffer.
+ * Caller must free digest which is allocated by sshkey_fingerprint_raw().
*/
static int
dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
@@ -86,32 +87,21 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
switch (key->type) {
case KEY_RSA:
*algorithm = SSHFP_KEY_RSA;
- if (!*digest_type)
- *digest_type = SSHFP_HASH_SHA1;
break;
case KEY_DSA:
*algorithm = SSHFP_KEY_DSA;
- if (!*digest_type)
- *digest_type = SSHFP_HASH_SHA1;
break;
case KEY_ECDSA:
*algorithm = SSHFP_KEY_ECDSA;
- if (!*digest_type)
- *digest_type = SSHFP_HASH_SHA256;
break;
case KEY_ED25519:
*algorithm = SSHFP_KEY_ED25519;
- if (!*digest_type)
- *digest_type = SSHFP_HASH_SHA256;
break;
case KEY_XMSS:
*algorithm = SSHFP_KEY_XMSS;
- if (!*digest_type)
- *digest_type = SSHFP_HASH_SHA256;
break;
default:
*algorithm = SSHFP_KEY_RESERVED; /* 0 */
- *digest_type = SSHFP_HASH_RESERVED; /* 0 */
}
switch (*digest_type) {
@@ -128,13 +118,11 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
if (*algorithm && *digest_type) {
if ((r = sshkey_fingerprint_raw(key, fp_alg, digest,
digest_len)) != 0)
- fatal("%s: sshkey_fingerprint_raw: %s", __func__,
- ssh_err(r));
+ fatal_fr(r, "sshkey_fingerprint_raw");
success = 1;
} else {
*digest = NULL;
*digest_len = 0;
- success = 0;
}
return success;
@@ -213,7 +201,6 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
struct rrsetinfo *fingerprints = NULL;
u_int8_t hostkey_algorithm;
- u_int8_t hostkey_digest_type = SSHFP_HASH_RESERVED;
u_char *hostkey_digest;
size_t hostkey_digest_len;
@@ -255,16 +242,6 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
fingerprints->rri_nrdatas);
}
- /* Initialize default host key parameters */
- if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type,
- &hostkey_digest, &hostkey_digest_len, hostkey)) {
- error("Error calculating host key fingerprint.");
-#if !defined(ANDROID)
- freerrset(fingerprints);
-#endif
- return -1;
- }
-
if (fingerprints->rri_nrdatas)
*flags |= DNS_VERIFY_FOUND;
@@ -280,39 +257,45 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
verbose("Error parsing fingerprint from DNS.");
continue;
}
+ debug3_f("checking SSHFP type %d fptype %d", dnskey_algorithm,
+ dnskey_digest_type);
- if (hostkey_digest_type != dnskey_digest_type) {
- hostkey_digest_type = dnskey_digest_type;
- free(hostkey_digest);
-
- /* Initialize host key parameters */
- if (!dns_read_key(&hostkey_algorithm,
- &hostkey_digest_type, &hostkey_digest,
- &hostkey_digest_len, hostkey)) {
- error("Error calculating key fingerprint.");
+ /* Calculate host key fingerprint. */
+ if (!dns_read_key(&hostkey_algorithm, &dnskey_digest_type,
+ &hostkey_digest, &hostkey_digest_len, hostkey)) {
+ error("Error calculating key fingerprint.");
#if !defined(ANDROID)
- freerrset(fingerprints);
+ freerrset(fingerprints);
#endif
- return -1;
- }
+ return -1;
}
/* Check if the current key is the same as the given key */
if (hostkey_algorithm == dnskey_algorithm &&
- hostkey_digest_type == dnskey_digest_type) {
- if (hostkey_digest_len == dnskey_digest_len &&
- timingsafe_bcmp(hostkey_digest, dnskey_digest,
- hostkey_digest_len) == 0)
+ hostkey_digest_len == dnskey_digest_len) {
+ if (timingsafe_bcmp(hostkey_digest, dnskey_digest,
+ hostkey_digest_len) == 0) {
+ debug_f("matched SSHFP type %d fptype %d",
+ dnskey_algorithm, dnskey_digest_type);
*flags |= DNS_VERIFY_MATCH;
+ } else {
+ debug_f("failed SSHFP type %d fptype %d",
+ dnskey_algorithm, dnskey_digest_type);
+ *flags |= DNS_VERIFY_FAILED;
+ }
}
free(dnskey_digest);
+ free(hostkey_digest); /* from sshkey_fingerprint_raw() */
}
- free(hostkey_digest); /* from sshkey_fingerprint_raw() */
#if !defined(ANDROID)
freerrset(fingerprints);
#endif
+ /* If any fingerprint failed to validate, return failure. */
+ if (*flags & DNS_VERIFY_FAILED)
+ *flags &= ~DNS_VERIFY_MATCH;
+
if (*flags & DNS_VERIFY_FOUND)
if (*flags & DNS_VERIFY_MATCH)
debug("matching host key fingerprint found in DNS");
@@ -360,7 +343,7 @@ export_dns_rr(const char *hostname, struct sshkey *key, FILE *f, int generic)
/* No SSHFP record was generated at all */
if (success == 0) {
- error("%s: unsupported algorithm and/or digest_type", __func__);
+ error_f("unsupported algorithm and/or digest_type");
}
return success;
diff --git a/dns.h b/dns.h
index 91f3c632d..c9b61c4f2 100644
--- a/dns.h
+++ b/dns.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dns.h,v 1.18 2018/02/23 15:58:37 markus Exp $ */
+/* $OpenBSD: dns.h,v 1.19 2021/07/19 03:13:28 dtucker Exp $ */
/*
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
@@ -50,6 +50,7 @@ enum sshfp_hashes {
#define DNS_VERIFY_FOUND 0x00000001
#define DNS_VERIFY_MATCH 0x00000002
#define DNS_VERIFY_SECURE 0x00000004
+#define DNS_VERIFY_FAILED 0x00000008
int verify_host_key_dns(const char *, struct sockaddr *,
struct sshkey *, int *);
diff --git a/entropy.c b/entropy.c
index 19ddeeafa..a4088e43c 100644
--- a/entropy.c
+++ b/entropy.c
@@ -29,20 +29,12 @@
#ifdef WITH_OPENSSL
#include <sys/types.h>
-#include <sys/socket.h>
-#ifdef HAVE_SYS_UN_H
-# include <sys/un.h>
-#endif
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <stddef.h> /* for offsetof */
#include <openssl/rand.h>
#include <openssl/crypto.h>
@@ -67,121 +59,6 @@
*/
#ifndef OPENSSL_PRNG_ONLY
-/*
- * Collect 'len' bytes of entropy into 'buf' from PRNGD/EGD daemon
- * listening either on 'tcp_port', or via Unix domain socket at *
- * 'socket_path'.
- * Either a non-zero tcp_port or a non-null socket_path must be
- * supplied.
- * Returns 0 on success, -1 on error
- */
-int
-get_random_bytes_prngd(unsigned char *buf, int len,
- unsigned short tcp_port, char *socket_path)
-{
- int fd, addr_len, rval, errors;
- u_char msg[2];
- struct sockaddr_storage addr;
- struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
- struct sockaddr_un *addr_un = (struct sockaddr_un *)&addr;
- sshsig_t old_sigpipe;
-
- /* Sanity checks */
- if (socket_path == NULL && tcp_port == 0)
- fatal("You must specify a port or a socket");
- if (socket_path != NULL &&
- strlen(socket_path) >= sizeof(addr_un->sun_path))
- fatal("Random pool path is too long");
- if (len <= 0 || len > 255)
- fatal("Too many bytes (%d) to read from PRNGD", len);
-
- memset(&addr, '\0', sizeof(addr));
-
- if (tcp_port != 0) {
- addr_in->sin_family = AF_INET;
- addr_in->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- addr_in->sin_port = htons(tcp_port);
- addr_len = sizeof(*addr_in);
- } else {
- addr_un->sun_family = AF_UNIX;
- strlcpy(addr_un->sun_path, socket_path,
- sizeof(addr_un->sun_path));
- addr_len = offsetof(struct sockaddr_un, sun_path) +
- strlen(socket_path) + 1;
- }
-
- old_sigpipe = ssh_signal(SIGPIPE, SIG_IGN);
-
- errors = 0;
- rval = -1;
-reopen:
- fd = socket(addr.ss_family, SOCK_STREAM, 0);
- if (fd == -1) {
- error("Couldn't create socket: %s", strerror(errno));
- goto done;
- }
-
- if (connect(fd, (struct sockaddr*)&addr, addr_len) == -1) {
- if (tcp_port != 0) {
- error("Couldn't connect to PRNGD port %d: %s",
- tcp_port, strerror(errno));
- } else {
- error("Couldn't connect to PRNGD socket \"%s\": %s",
- addr_un->sun_path, strerror(errno));
- }
- goto done;
- }
-
- /* Send blocking read request to PRNGD */
- msg[0] = 0x02;
- msg[1] = len;
-
- if (atomicio(vwrite, fd, msg, sizeof(msg)) != sizeof(msg)) {
- if (errno == EPIPE && errors < 10) {
- close(fd);
- errors++;
- goto reopen;
- }
- error("Couldn't write to PRNGD socket: %s",
- strerror(errno));
- goto done;
- }
-
- if (atomicio(read, fd, buf, len) != (size_t)len) {
- if (errno == EPIPE && errors < 10) {
- close(fd);
- errors++;
- goto reopen;
- }
- error("Couldn't read from PRNGD socket: %s",
- strerror(errno));
- goto done;
- }
-
- rval = 0;
-done:
- ssh_signal(SIGPIPE, old_sigpipe);
- if (fd != -1)
- close(fd);
- return rval;
-}
-
-static int
-seed_from_prngd(unsigned char *buf, size_t bytes)
-{
-#ifdef PRNGD_PORT
- debug("trying egd/prngd port %d", PRNGD_PORT);
- if (get_random_bytes_prngd(buf, bytes, PRNGD_PORT, NULL) == 0)
- return 0;
-#endif
-#ifdef PRNGD_SOCKET
- debug("trying egd/prngd socket %s", PRNGD_SOCKET);
- if (get_random_bytes_prngd(buf, bytes, 0, PRNGD_SOCKET) == 0)
- return 0;
-#endif
- return -1;
-}
-
void
rexec_send_rng_seed(struct sshbuf *m)
{
diff --git a/fatal.c b/fatal.c
index 5e5aa3fe1..16fbd3204 100644
--- a/fatal.c
+++ b/fatal.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fatal.c,v 1.7 2006/08/03 03:34:42 deraadt Exp $ */
+/* $OpenBSD: fatal.c,v 1.11 2020/10/19 08:07:08 djm Exp $ */
/*
* Copyright (c) 2002 Markus Friedl. All rights reserved.
*
@@ -34,12 +34,13 @@
/* Fatal messages. This function never returns. */
void
-fatal(const char *fmt,...)
+sshfatal(const char *file, const char *func, int line, int showfunc,
+ LogLevel level, const char *suffix, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
- do_log(SYSLOG_LEVEL_FATAL, fmt, args);
+ sshlogv(file, func, line, showfunc, level, suffix, fmt, args);
va_end(args);
cleanup_exit(255);
}
diff --git a/gss-genr.c b/gss-genr.c
index d56257b4a..685280517 100644
--- a/gss-genr.c
+++ b/gss-genr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gss-genr.c,v 1.26 2018/07/10 09:13:30 djm Exp $ */
+/* $OpenBSD: gss-genr.c,v 1.28 2021/01/27 10:05:28 djm Exp $ */
/*
* Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved.
@@ -44,9 +44,6 @@
#include "ssh-gss.h"
-extern u_char *session_id2;
-extern u_int session_id2_len;
-
/* sshbuf_get for gss_buffer_desc */
int
ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g)
@@ -115,7 +112,7 @@ ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status,
int r;
if ((b = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if (major_status != NULL)
*major_status = ctxt->major;
@@ -130,7 +127,7 @@ ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status,
if ((r = sshbuf_put(b, msg.value, msg.length)) != 0 ||
(r = sshbuf_put_u8(b, '\n')) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble GSS_CODE");
gss_release_buffer(&lmin, &msg);
} while (ctx != 0);
@@ -142,13 +139,13 @@ ssh_gssapi_last_error(Gssctxt *ctxt, OM_uint32 *major_status,
if ((r = sshbuf_put(b, msg.value, msg.length)) != 0 ||
(r = sshbuf_put_u8(b, '\n')) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble MECH_CODE");
gss_release_buffer(&lmin, &msg);
} while (ctx != 0);
if ((r = sshbuf_put_u8(b, '\n')) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble newline");
ret = xstrdup((const char *)sshbuf_ptr(b));
sshbuf_free(b);
return (ret);
@@ -259,17 +256,17 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
void
ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service,
- const char *context)
+ const char *context, const struct sshbuf *session_id)
{
int r;
sshbuf_reset(b);
- if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 ||
+ if ((r = sshbuf_put_stringb(b, session_id)) != 0 ||
(r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
(r = sshbuf_put_cstring(b, user)) != 0 ||
(r = sshbuf_put_cstring(b, service)) != 0 ||
(r = sshbuf_put_cstring(b, context)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble buildmic");
}
int
diff --git a/hash.c b/hash.c
index fb81e4786..b4f8f6c50 100644
--- a/hash.c
+++ b/hash.c
@@ -1,5 +1,3 @@
-/* $OpenBSD: hash.c,v 1.4 2017/12/14 21:07:39 naddy Exp $ */
-
/* $OpenBSD: hash.c,v 1.6 2019/11/29 00:11:21 djm Exp $ */
/*
* Public domain. Author: Christian Weisgerber <naddy@openbsd.org>
diff --git a/hostfile.c b/hostfile.c
index a4a355972..ce00cd713 100644
--- a/hostfile.c
+++ b/hostfile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hostfile.c,v 1.79 2020/03/06 18:25:12 markus Exp $ */
+/* $OpenBSD: hostfile.c,v 1.91 2021/07/05 01:16:46 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -57,14 +57,11 @@
#include "hostfile.h"
#include "log.h"
#include "misc.h"
+#include "pathnames.h"
#include "ssherr.h"
#include "digest.h"
#include "hmac.h"
-
-struct hostkeys {
- struct hostkey_entry *entries;
- u_int num_entries;
-};
+#include "sshbuf.h"
/* XXX hmac is too easy to dictionary attack; use bcrypt? */
@@ -140,12 +137,12 @@ host_hash(const char *host, const char *name_from_hostfile, u_int src_len)
ssh_hmac_init(ctx, salt, len) < 0 ||
ssh_hmac_update(ctx, host, strlen(host)) < 0 ||
ssh_hmac_final(ctx, result, sizeof(result)))
- fatal("%s: ssh_hmac failed", __func__);
+ fatal_f("ssh_hmac failed");
ssh_hmac_free(ctx);
if (__b64_ntop(salt, len, uu_salt, sizeof(uu_salt)) == -1 ||
__b64_ntop(result, len, uu_result, sizeof(uu_result)) == -1)
- fatal("%s: __b64_ntop failed", __func__);
+ fatal_f("__b64_ntop failed");
snprintf(encoded, sizeof(encoded), "%s%s%c%s", HASH_MAGIC, uu_salt,
HASH_DELIM, uu_result);
@@ -245,7 +242,7 @@ record_hostkey(struct hostkey_foreach_line *l, void *_ctx)
return 0;
}
- debug3("%s: found %skey type %s in file %s:%lu", __func__,
+ debug3_f("found %skey type %s in file %s:%lu",
l->marker == MRK_NONE ? "" :
(l->marker == MRK_CA ? "ca " : "revoked "),
sshkey_type(l->key), l->path, l->linenum);
@@ -259,6 +256,7 @@ record_hostkey(struct hostkey_foreach_line *l, void *_ctx)
hostkeys->entries[hostkeys->num_entries].key = l->key;
l->key = NULL; /* steal it */
hostkeys->entries[hostkeys->num_entries].marker = l->marker;
+ hostkeys->entries[hostkeys->num_entries].note = l->note;
hostkeys->num_entries++;
ctx->num_loaded++;
@@ -266,7 +264,8 @@ record_hostkey(struct hostkey_foreach_line *l, void *_ctx)
}
void
-load_hostkeys(struct hostkeys *hostkeys, const char *host, const char *path)
+load_hostkeys_file(struct hostkeys *hostkeys, const char *host,
+ const char *path, FILE *f, u_int note)
{
int r;
struct load_callback_ctx ctx;
@@ -275,15 +274,28 @@ load_hostkeys(struct hostkeys *hostkeys, const char *host, const char *path)
ctx.num_loaded = 0;
ctx.hostkeys = hostkeys;
- if ((r = hostkeys_foreach(path, record_hostkey, &ctx, host, NULL,
- HKF_WANT_MATCH|HKF_WANT_PARSE_KEY)) != 0) {
+ if ((r = hostkeys_foreach_file(path, f, record_hostkey, &ctx, host,
+ NULL, HKF_WANT_MATCH|HKF_WANT_PARSE_KEY, note)) != 0) {
if (r != SSH_ERR_SYSTEM_ERROR && errno != ENOENT)
- debug("%s: hostkeys_foreach failed for %s: %s",
- __func__, path, ssh_err(r));
+ debug_fr(r, "hostkeys_foreach failed for %s", path);
}
if (ctx.num_loaded != 0)
- debug3("%s: loaded %lu keys from %s", __func__,
- ctx.num_loaded, host);
+ debug3_f("loaded %lu keys from %s", ctx.num_loaded, host);
+}
+
+void
+load_hostkeys(struct hostkeys *hostkeys, const char *host, const char *path,
+ u_int note)
+{
+ FILE *f;
+
+ if ((f = fopen(path, "r")) == NULL) {
+ debug_f("fopen %s: %s", path, strerror(errno));
+ return;
+ }
+
+ load_hostkeys_file(hostkeys, host, path, f, note);
+ fclose(f);
}
void
@@ -337,7 +349,7 @@ check_key_not_revoked(struct hostkeys *hostkeys, struct sshkey *k)
*/
static HostStatus
check_hostkeys_by_key_or_type(struct hostkeys *hostkeys,
- struct sshkey *k, int keytype, const struct hostkey_entry **found)
+ struct sshkey *k, int keytype, int nid, const struct hostkey_entry **found)
{
u_int i;
HostStatus end_return = HOST_NEW;
@@ -353,6 +365,10 @@ check_hostkeys_by_key_or_type(struct hostkeys *hostkeys,
if (k == NULL) {
if (hostkeys->entries[i].key->type != keytype)
continue;
+ if (nid != -1 &&
+ sshkey_type_plain(keytype) == KEY_ECDSA &&
+ hostkeys->entries[i].key->ecdsa_nid != nid)
+ continue;
end_return = HOST_FOUND;
if (found != NULL)
*found = hostkeys->entries + i;
@@ -375,7 +391,7 @@ check_hostkeys_by_key_or_type(struct hostkeys *hostkeys,
*found = hostkeys->entries + i;
break;
}
- /* A non-maching key exists */
+ /* A non-matching key exists */
end_return = HOST_CHANGED;
if (found != NULL)
*found = hostkeys->entries + i;
@@ -395,17 +411,29 @@ check_key_in_hostkeys(struct hostkeys *hostkeys, struct sshkey *key,
{
if (key == NULL)
fatal("no key to look up");
- return check_hostkeys_by_key_or_type(hostkeys, key, 0, found);
+ return check_hostkeys_by_key_or_type(hostkeys, key, 0, -1, found);
}
int
-lookup_key_in_hostkeys_by_type(struct hostkeys *hostkeys, int keytype,
+lookup_key_in_hostkeys_by_type(struct hostkeys *hostkeys, int keytype, int nid,
const struct hostkey_entry **found)
{
- return (check_hostkeys_by_key_or_type(hostkeys, NULL, keytype,
+ return (check_hostkeys_by_key_or_type(hostkeys, NULL, keytype, nid,
found) == HOST_FOUND);
}
+int
+lookup_marker_in_hostkeys(struct hostkeys *hostkeys, int want_marker)
+{
+ u_int i;
+
+ for (i = 0; i < hostkeys->num_entries; i++) {
+ if (hostkeys->entries[i].marker == (HostkeyMarker)want_marker)
+ return 1;
+ }
+ return 0;
+}
+
static int
write_host_entry(FILE *f, const char *host, const char *ip,
const struct sshkey *key, int store_hash)
@@ -418,7 +446,7 @@ write_host_entry(FILE *f, const char *host, const char *ip,
if (store_hash) {
if ((hashed_host = host_hash(lhost, NULL, 0)) == NULL) {
- error("%s: host_hash failed", __func__);
+ error_f("host_hash failed");
free(lhost);
return 0;
}
@@ -432,12 +460,53 @@ write_host_entry(FILE *f, const char *host, const char *ip,
if ((r = sshkey_write(key, f)) == 0)
success = 1;
else
- error("%s: sshkey_write failed: %s", __func__, ssh_err(r));
+ error_fr(r, "sshkey_write");
fputc('\n', f);
+ /* If hashing is enabled, the IP address needs to go on its own line */
+ if (success && store_hash && ip != NULL)
+ success = write_host_entry(f, ip, NULL, key, 1);
return success;
}
/*
+ * Create user ~/.ssh directory if it doesn't exist and we want to write to it.
+ * If notify is set, a message will be emitted if the directory is created.
+ */
+void
+hostfile_create_user_ssh_dir(const char *filename, int notify)
+{
+ char *dotsshdir = NULL, *p;
+ size_t len;
+ struct stat st;
+
+ if ((p = strrchr(filename, '/')) == NULL)
+ return;
+ len = p - filename;
+ dotsshdir = tilde_expand_filename("~/" _PATH_SSH_USER_DIR, getuid());
+ if (strlen(dotsshdir) > len || strncmp(filename, dotsshdir, len) != 0)
+ goto out; /* not ~/.ssh prefixed */
+ if (stat(dotsshdir, &st) == 0)
+ goto out; /* dir already exists */
+ else if (errno != ENOENT)
+ error("Could not stat %s: %s", dotsshdir, strerror(errno));
+ else {
+#ifdef WITH_SELINUX
+ ssh_selinux_setfscreatecon(dotsshdir);
+#endif
+ if (mkdir(dotsshdir, 0700) == -1)
+ error("Could not create directory '%.200s' (%s).",
+ dotsshdir, strerror(errno));
+ else if (notify)
+ logit("Created directory '%s'.", dotsshdir);
+#ifdef WITH_SELINUX
+ ssh_selinux_setfscreatecon(NULL);
+#endif
+ }
+ out:
+ free(dotsshdir);
+}
+
+/*
* Appends an entry to the host file. Returns false if the entry could not
* be appended.
*/
@@ -450,6 +519,7 @@ add_host_to_hostfile(const char *filename, const char *host,
if (key == NULL)
return 1; /* XXX ? */
+ hostfile_create_user_ssh_dir(filename, 0);
f = fopen(filename, "a");
if (!f)
return 0;
@@ -461,8 +531,8 @@ add_host_to_hostfile(const char *filename, const char *host,
struct host_delete_ctx {
FILE *out;
int quiet;
- const char *host;
- int *skip_keys; /* XXX split for host/ip? might want to ensure both */
+ const char *host, *ip;
+ u_int *match_keys; /* mask of HKF_MATCH_* for this key */
struct sshkey * const *keys;
size_t nkeys;
int modified;
@@ -475,26 +545,21 @@ host_delete(struct hostkey_foreach_line *l, void *_ctx)
int loglevel = ctx->quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_VERBOSE;
size_t i;
- if (l->status == HKF_STATUS_MATCHED) {
- if (l->marker != MRK_NONE) {
- /* Don't remove CA and revocation lines */
- fprintf(ctx->out, "%s\n", l->line);
- return 0;
- }
-
+ /* Don't remove CA and revocation lines */
+ if (l->status == HKF_STATUS_MATCHED && l->marker == MRK_NONE) {
/*
* If this line contains one of the keys that we will be
* adding later, then don't change it and mark the key for
* skipping.
*/
for (i = 0; i < ctx->nkeys; i++) {
- if (sshkey_equal(ctx->keys[i], l->key)) {
- ctx->skip_keys[i] = 1;
- fprintf(ctx->out, "%s\n", l->line);
- debug3("%s: %s key already at %s:%ld", __func__,
- sshkey_type(l->key), l->path, l->linenum);
- return 0;
- }
+ if (!sshkey_equal(ctx->keys[i], l->key))
+ continue;
+ ctx->match_keys[i] |= l->match;
+ fprintf(ctx->out, "%s\n", l->line);
+ debug3_f("%s key already at %s:%ld",
+ sshkey_type(l->key), l->path, l->linenum);
+ return 0;
}
/*
@@ -525,15 +590,19 @@ hostfile_replace_entries(const char *filename, const char *host, const char *ip,
int loglevel = quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_VERBOSE;
struct host_delete_ctx ctx;
char *fp, *temp = NULL, *back = NULL;
+ const char *what;
mode_t omask;
size_t i;
+ u_int want;
omask = umask(077);
memset(&ctx, 0, sizeof(ctx));
ctx.host = host;
+ ctx.ip = ip;
ctx.quiet = quiet;
- if ((ctx.skip_keys = calloc(nkeys, sizeof(*ctx.skip_keys))) == NULL)
+
+ if ((ctx.match_keys = calloc(nkeys, sizeof(*ctx.match_keys))) == NULL)
return SSH_ERR_ALLOC_FAIL;
ctx.keys = keys;
ctx.nkeys = nkeys;
@@ -550,43 +619,65 @@ hostfile_replace_entries(const char *filename, const char *host, const char *ip,
if ((fd = mkstemp(temp)) == -1) {
oerrno = errno;
- error("%s: mkstemp: %s", __func__, strerror(oerrno));
+ error_f("mkstemp: %s", strerror(oerrno));
r = SSH_ERR_SYSTEM_ERROR;
goto fail;
}
if ((ctx.out = fdopen(fd, "w")) == NULL) {
oerrno = errno;
close(fd);
- error("%s: fdopen: %s", __func__, strerror(oerrno));
+ error_f("fdopen: %s", strerror(oerrno));
r = SSH_ERR_SYSTEM_ERROR;
goto fail;
}
- /* Remove all entries for the specified host from the file */
+ /* Remove stale/mismatching entries for the specified host */
if ((r = hostkeys_foreach(filename, host_delete, &ctx, host, ip,
- HKF_WANT_PARSE_KEY)) != 0) {
+ HKF_WANT_PARSE_KEY, 0)) != 0) {
oerrno = errno;
- error("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r));
+ error_fr(r, "hostkeys_foreach");
goto fail;
}
- /* Add the requested keys */
+ /* Re-add the requested keys */
+ want = HKF_MATCH_HOST | (ip == NULL ? 0 : HKF_MATCH_IP);
for (i = 0; i < nkeys; i++) {
- if (ctx.skip_keys[i])
+ if ((want & ctx.match_keys[i]) == want)
continue;
if ((fp = sshkey_fingerprint(keys[i], hash_alg,
SSH_FP_DEFAULT)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto fail;
}
- do_log2(loglevel, "%s%sAdding new key for %s to %s: %s %s",
- quiet ? __func__ : "", quiet ? ": " : "", host, filename,
+ /* write host/ip */
+ what = "";
+ if (ctx.match_keys[i] == 0) {
+ what = "Adding new key";
+ if (!write_host_entry(ctx.out, host, ip,
+ keys[i], store_hash)) {
+ r = SSH_ERR_INTERNAL_ERROR;
+ goto fail;
+ }
+ } else if ((want & ~ctx.match_keys[i]) == HKF_MATCH_HOST) {
+ what = "Fixing match (hostname)";
+ if (!write_host_entry(ctx.out, host, NULL,
+ keys[i], store_hash)) {
+ r = SSH_ERR_INTERNAL_ERROR;
+ goto fail;
+ }
+ } else if ((want & ~ctx.match_keys[i]) == HKF_MATCH_IP) {
+ what = "Fixing match (address)";
+ if (!write_host_entry(ctx.out, ip, NULL,
+ keys[i], store_hash)) {
+ r = SSH_ERR_INTERNAL_ERROR;
+ goto fail;
+ }
+ }
+ do_log2(loglevel, "%s%s%s for %s%s%s to %s: %s %s",
+ quiet ? __func__ : "", quiet ? ": " : "", what,
+ host, ip == NULL ? "" : ",", ip == NULL ? "" : ip, filename,
sshkey_ssh_name(keys[i]), fp);
free(fp);
- if (!write_host_entry(ctx.out, host, ip, keys[i], store_hash)) {
- r = SSH_ERR_INTERNAL_ERROR;
- goto fail;
- }
ctx.modified = 1;
}
fclose(ctx.out);
@@ -596,30 +687,28 @@ hostfile_replace_entries(const char *filename, const char *host, const char *ip,
/* Backup the original file and replace it with the temporary */
if (unlink(back) == -1 && errno != ENOENT) {
oerrno = errno;
- error("%s: unlink %.100s: %s", __func__,
- back, strerror(errno));
+ error_f("unlink %.100s: %s", back, strerror(errno));
r = SSH_ERR_SYSTEM_ERROR;
goto fail;
}
if (link(filename, back) == -1) {
oerrno = errno;
- error("%s: link %.100s to %.100s: %s", __func__,
- filename, back, strerror(errno));
+ error_f("link %.100s to %.100s: %s", filename,
+ back, strerror(errno));
r = SSH_ERR_SYSTEM_ERROR;
goto fail;
}
if (rename(temp, filename) == -1) {
oerrno = errno;
- error("%s: rename \"%s\" to \"%s\": %s", __func__,
- temp, filename, strerror(errno));
+ error_f("rename \"%s\" to \"%s\": %s", temp,
+ filename, strerror(errno));
r = SSH_ERR_SYSTEM_ERROR;
goto fail;
}
} else {
/* No changes made; just delete the temporary file */
if (unlink(temp) != 0)
- error("%s: unlink \"%s\": %s", __func__,
- temp, strerror(errno));
+ error_f("unlink \"%s\": %s", temp, strerror(errno));
}
/* success */
@@ -631,7 +720,7 @@ hostfile_replace_entries(const char *filename, const char *host, const char *ip,
free(back);
if (ctx.out != NULL)
fclose(ctx.out);
- free(ctx.skip_keys);
+ free(ctx.match_keys);
umask(omask);
if (r == SSH_ERR_SYSTEM_ERROR)
errno = oerrno;
@@ -657,10 +746,9 @@ match_maybe_hashed(const char *host, const char *names, int *was_hashed)
}
int
-hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
- const char *host, const char *ip, u_int options)
+hostkeys_foreach_file(const char *path, FILE *f, hostkeys_foreach_fn *callback,
+ void *ctx, const char *host, const char *ip, u_int options, u_int note)
{
- FILE *f;
char *line = NULL, ktype[128];
u_long linenum = 0;
char *cp, *cp2;
@@ -673,10 +761,7 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
memset(&lineinfo, 0, sizeof(lineinfo));
if (host == NULL && (options & HKF_WANT_MATCH) != 0)
return SSH_ERR_INVALID_ARGUMENT;
- if ((f = fopen(path, "r")) == NULL)
- return SSH_ERR_SYSTEM_ERROR;
- debug3("%s: reading file \"%s\"", __func__, path);
while (getline(&line, &linesize, f) != -1) {
linenum++;
line[strcspn(line, "\n")] = '\0';
@@ -690,6 +775,7 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
lineinfo.marker = MRK_NONE;
lineinfo.status = HKF_STATUS_OK;
lineinfo.keytype = KEY_UNSPEC;
+ lineinfo.note = note;
/* Skip any leading whitespace, comments and empty lines. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
@@ -704,8 +790,7 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
}
if ((lineinfo.marker = check_markers(&cp)) == MRK_ERROR) {
- verbose("%s: invalid marker at %s:%lu",
- __func__, path, linenum);
+ verbose_f("invalid marker at %s:%lu", path, linenum);
if ((options & HKF_WANT_MATCH) == 0)
goto bad;
continue;
@@ -721,8 +806,8 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
if (host != NULL) {
if ((s = match_maybe_hashed(host, lineinfo.hosts,
&hashed)) == -1) {
- debug2("%s: %s:%ld: bad host hash \"%.32s\"",
- __func__, path, linenum, lineinfo.hosts);
+ debug2_f("%s:%ld: bad host hash \"%.32s\"",
+ path, linenum, lineinfo.hosts);
goto bad;
}
if (s == 1) {
@@ -734,9 +819,9 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
if (ip != NULL) {
if ((s = match_maybe_hashed(ip, lineinfo.hosts,
&hashed)) == -1) {
- debug2("%s: %s:%ld: bad ip hash "
- "\"%.32s\"", __func__, path,
- linenum, lineinfo.hosts);
+ debug2_f("%s:%ld: bad ip hash "
+ "\"%.32s\"", path, linenum,
+ lineinfo.hosts);
goto bad;
}
if (s == 1) {
@@ -771,7 +856,7 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
* lines.
*/
if ((lineinfo.key = sshkey_new(KEY_UNSPEC)) == NULL) {
- error("%s: sshkey_new failed", __func__);
+ error_f("sshkey_new failed");
r = SSH_ERR_ALLOC_FAIL;
break;
}
@@ -827,6 +912,24 @@ hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
sshkey_free(lineinfo.key);
free(lineinfo.line);
free(line);
+ return r;
+}
+
+int
+hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
+ const char *host, const char *ip, u_int options, u_int note)
+{
+ FILE *f;
+ int r, oerrno;
+
+ if ((f = fopen(path, "r")) == NULL)
+ return SSH_ERR_SYSTEM_ERROR;
+
+ debug3_f("reading file \"%s\"", path);
+ r = hostkeys_foreach_file(path, f, callback, ctx, host, ip,
+ options, note);
+ oerrno = errno;
fclose(f);
+ errno = oerrno;
return r;
}
diff --git a/hostfile.h b/hostfile.h
index bd2104373..a24a4e329 100644
--- a/hostfile.h
+++ b/hostfile.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: hostfile.h,v 1.24 2015/02/16 22:08:57 djm Exp $ */
+/* $OpenBSD: hostfile.h,v 1.29 2021/01/26 00:51:30 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -28,17 +28,25 @@ struct hostkey_entry {
u_long line;
struct sshkey *key;
HostkeyMarker marker;
+ u_int note; /* caller-specific note/flag */
+};
+struct hostkeys {
+ struct hostkey_entry *entries;
+ u_int num_entries;
};
-struct hostkeys;
struct hostkeys *init_hostkeys(void);
-void load_hostkeys(struct hostkeys *, const char *, const char *);
+void load_hostkeys(struct hostkeys *, const char *,
+ const char *, u_int);
+void load_hostkeys_file(struct hostkeys *, const char *,
+ const char *, FILE *, u_int note);
void free_hostkeys(struct hostkeys *);
HostStatus check_key_in_hostkeys(struct hostkeys *, struct sshkey *,
const struct hostkey_entry **);
-int lookup_key_in_hostkeys_by_type(struct hostkeys *, int,
+int lookup_key_in_hostkeys_by_type(struct hostkeys *, int, int,
const struct hostkey_entry **);
+int lookup_marker_in_hostkeys(struct hostkeys *, int);
int hostfile_read_key(char **, u_int *, struct sshkey *);
int add_host_to_hostfile(const char *, const char *,
@@ -92,6 +100,7 @@ struct hostkey_foreach_line {
int keytype; /* Type of key; KEY_UNSPEC for invalid/comment lines */
struct sshkey *key; /* Key, if parsed ok and HKF_WANT_MATCH_HOST set */
const char *comment; /* Any comment following the key */
+ u_int note; /* caller-specified note copied from arguments */
};
/*
@@ -102,7 +111,13 @@ struct hostkey_foreach_line {
typedef int hostkeys_foreach_fn(struct hostkey_foreach_line *l, void *ctx);
/* Iterate over a hostkeys file */
-int hostkeys_foreach(const char *path, hostkeys_foreach_fn *callback, void *ctx,
- const char *host, const char *ip, u_int options);
+int hostkeys_foreach(const char *path,
+ hostkeys_foreach_fn *callback, void *ctx,
+ const char *host, const char *ip, u_int options, u_int note);
+int hostkeys_foreach_file(const char *path, FILE *f,
+ hostkeys_foreach_fn *callback, void *ctx,
+ const char *host, const char *ip, u_int options, u_int note);
+
+void hostfile_create_user_ssh_dir(const char *, int);
#endif
diff --git a/int32_minmax.inc b/int32_minmax.inc
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/int32_minmax.inc
diff --git a/kex.c b/kex.c
index 09c7258e0..709a0ec63 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.c,v 1.158 2020/03/13 04:01:56 djm Exp $ */
+/* $OpenBSD: kex.c,v 1.168 2021/04/03 06:18:40 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
@@ -110,8 +110,10 @@ static const struct kexalg kexalgs[] = {
#if defined(HAVE_EVP_SHA256) || !defined(WITH_OPENSSL)
{ KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
{ KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
- { KEX_SNTRUP4591761X25519_SHA512, KEX_KEM_SNTRUP4591761X25519_SHA512, 0,
+#ifdef USE_SNTRUP761X25519
+ { KEX_SNTRUP761X25519_SHA512, KEX_KEM_SNTRUP761X25519_SHA512, 0,
SSH_DIGEST_SHA512 },
+#endif
#endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */
{ NULL, 0, -1, -1},
};
@@ -247,7 +249,7 @@ kex_assemble_names(char **listp, const char *def, const char *all)
list = tmp;
} else if (*list == '-') {
/* Remove names from default list */
- if ((*listp = match_filter_blacklist(def, list + 1)) == NULL) {
+ if ((*listp = match_filter_denylist(def, list + 1)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto fail;
}
@@ -284,7 +286,7 @@ kex_assemble_names(char **listp, const char *def, const char *all)
goto fail;
}
free(matching);
- if ((matching = match_filter_whitelist(all, cp)) == NULL) {
+ if ((matching = match_filter_allowlist(all, cp)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto fail;
}
@@ -360,14 +362,13 @@ kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp)
goto out;
}
if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) { /* skip cookie */
- error("%s: consume cookie: %s", __func__, ssh_err(r));
+ error_fr(r, "consume cookie");
goto out;
}
/* extract kex init proposal strings */
for (i = 0; i < PROPOSAL_MAX; i++) {
if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0) {
- error("%s: parse proposal %u: %s", __func__,
- i, ssh_err(r));
+ error_fr(r, "parse proposal %u", i);
goto out;
}
debug2("%s: %s", proposal_names[i], proposal[i]);
@@ -375,7 +376,7 @@ kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp)
/* first kex follows / reserved */
if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */
(r = sshbuf_get_u32(b, &i)) != 0) { /* reserved */
- error("%s: parse: %s", __func__, ssh_err(r));
+ error_fr(r, "parse");
goto out;
}
if (first_kex_follows != NULL)
@@ -404,7 +405,7 @@ kex_prop_free(char **proposal)
}
/* ARGSUSED */
-static int
+int
kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
{
int r;
@@ -439,7 +440,7 @@ kex_send_ext_info(struct ssh *ssh)
(r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 ||
(r = sshpkt_put_cstring(ssh, algs)) != 0 ||
(r = sshpkt_send(ssh)) != 0) {
- error("%s: compose: %s", __func__, ssh_err(r));
+ error_fr(r, "compose");
goto out;
}
/* success */
@@ -491,14 +492,14 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
if (strcmp(name, "server-sig-algs") == 0) {
/* Ensure no \0 lurking in value */
if (memchr(val, '\0', vlen) != NULL) {
- error("%s: nul byte in %s", __func__, name);
+ error_f("nul byte in %s", name);
return SSH_ERR_INVALID_FORMAT;
}
- debug("%s: %s=<%s>", __func__, name, val);
+ debug_f("%s=<%s>", name, val);
kex->server_sig_algs = val;
val = NULL;
} else
- debug("%s: %s (unrecognised)", __func__, name);
+ debug_f("%s (unrecognised)", name);
free(name);
free(val);
}
@@ -536,7 +537,7 @@ kex_send_kexinit(struct ssh *ssh)
int r;
if (kex == NULL) {
- error("%s: no hex", __func__);
+ error_f("no kex");
return SSH_ERR_INTERNAL_ERROR;
}
if (kex->flags & KEX_INIT_SENT)
@@ -545,12 +546,12 @@ kex_send_kexinit(struct ssh *ssh)
/* generate a random cookie */
if (sshbuf_len(kex->my) < KEX_COOKIE_LEN) {
- error("%s: bad kex length: %zu < %d", __func__,
+ error_f("bad kex length: %zu < %d",
sshbuf_len(kex->my), KEX_COOKIE_LEN);
return SSH_ERR_INVALID_FORMAT;
}
if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL) {
- error("%s: buffer error", __func__);
+ error_f("buffer error");
return SSH_ERR_INTERNAL_ERROR;
}
arc4random_buf(cookie, KEX_COOKIE_LEN);
@@ -558,7 +559,7 @@ kex_send_kexinit(struct ssh *ssh)
if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 ||
(r = sshpkt_putb(ssh, kex->my)) != 0 ||
(r = sshpkt_send(ssh)) != 0) {
- error("%s: compose reply: %s", __func__, ssh_err(r));
+ error_fr(r, "compose reply");
return r;
}
debug("SSH2_MSG_KEXINIT sent");
@@ -578,7 +579,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
debug("SSH2_MSG_KEXINIT received");
if (kex == NULL) {
- error("%s: no hex", __func__);
+ error_f("no kex");
return SSH_ERR_INTERNAL_ERROR;
}
ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL);
@@ -589,13 +590,13 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
/* discard packet */
for (i = 0; i < KEX_COOKIE_LEN; i++) {
if ((r = sshpkt_get_u8(ssh, NULL)) != 0) {
- error("%s: discard cookie: %s", __func__, ssh_err(r));
+ error_fr(r, "discard cookie");
return r;
}
}
for (i = 0; i < PROPOSAL_MAX; i++) {
if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) {
- error("%s: discard proposal: %s", __func__, ssh_err(r));
+ error_fr(r, "discard proposal");
return r;
}
}
@@ -623,7 +624,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL)
return (kex->kex[kex->kex_type])(ssh);
- error("%s: unknown kex type %u", __func__, kex->kex_type);
+ error_f("unknown kex type %u", kex->kex_type);
return SSH_ERR_INTERNAL_ERROR;
}
@@ -636,7 +637,8 @@ kex_new(void)
(kex->peer = sshbuf_new()) == NULL ||
(kex->my = sshbuf_new()) == NULL ||
(kex->client_version = sshbuf_new()) == NULL ||
- (kex->server_version = sshbuf_new()) == NULL) {
+ (kex->server_version = sshbuf_new()) == NULL ||
+ (kex->session_id = sshbuf_new()) == NULL) {
kex_free(kex);
return NULL;
}
@@ -696,7 +698,7 @@ kex_free(struct kex *kex)
sshbuf_free(kex->client_version);
sshbuf_free(kex->server_version);
sshbuf_free(kex->client_pub);
- free(kex->session_id);
+ sshbuf_free(kex->session_id);
free(kex->failed_choice);
free(kex->hostkey_alg);
free(kex->name);
@@ -739,11 +741,11 @@ int
kex_start_rekex(struct ssh *ssh)
{
if (ssh->kex == NULL) {
- error("%s: no kex", __func__);
+ error_f("no kex");
return SSH_ERR_INTERNAL_ERROR;
}
if (ssh->kex->done == 0) {
- error("%s: requested twice", __func__);
+ error_f("requested twice");
return SSH_ERR_INTERNAL_ERROR;
}
ssh->kex->done = 0;
@@ -758,7 +760,7 @@ choose_enc(struct sshenc *enc, char *client, char *server)
if (name == NULL)
return SSH_ERR_NO_CIPHER_ALG_MATCH;
if ((enc->cipher = cipher_by_name(name)) == NULL) {
- error("%s: unsupported cipher %s", __func__, name);
+ error_f("unsupported cipher %s", name);
free(name);
return SSH_ERR_INTERNAL_ERROR;
}
@@ -780,7 +782,7 @@ choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server)
if (name == NULL)
return SSH_ERR_NO_MAC_ALG_MATCH;
if (mac_setup(mac, name) < 0) {
- error("%s: unsupported MAC %s", __func__, name);
+ error_f("unsupported MAC %s", name);
free(name);
return SSH_ERR_INTERNAL_ERROR;
}
@@ -807,7 +809,7 @@ choose_comp(struct sshcomp *comp, char *client, char *server)
if (strcmp(name, "none") == 0) {
comp->type = COMP_NONE;
} else {
- error("%s: unsupported compression scheme %s", __func__, name);
+ error_f("unsupported compression scheme %s", name);
free(name);
return SSH_ERR_INTERNAL_ERROR;
}
@@ -826,7 +828,7 @@ choose_kex(struct kex *k, char *client, char *server)
if (k->name == NULL)
return SSH_ERR_NO_KEX_ALG_MATCH;
if ((kexalg = kex_alg_by_name(k->name)) == NULL) {
- error("%s: unsupported KEX method %s", __func__, k->name);
+ error_f("unsupported KEX method %s", k->name);
return SSH_ERR_INTERNAL_ERROR;
}
k->kex_type = kexalg->type;
@@ -838,6 +840,7 @@ choose_kex(struct kex *k, char *client, char *server)
static int
choose_hostkeyalg(struct kex *k, char *client, char *server)
{
+ free(k->hostkey_alg);
k->hostkey_alg = match_list(client, server, NULL);
debug("kex: host key algorithm: %s",
@@ -846,8 +849,7 @@ choose_hostkeyalg(struct kex *k, char *client, char *server)
return SSH_ERR_NO_HOSTKEY_ALG_MATCH;
k->hostkey_type = sshkey_type_from_name(k->hostkey_alg);
if (k->hostkey_type == KEY_UNSPEC) {
- error("%s: unsupported hostkey algorithm %s", __func__,
- k->hostkey_alg);
+ error_f("unsupported hostkey algorithm %s", k->hostkey_alg);
return SSH_ERR_INTERNAL_ERROR;
}
k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg);
@@ -1014,11 +1016,10 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
ssh_digest_update(hashctx, hash, hashlen) != 0 ||
ssh_digest_update(hashctx, &c, 1) != 0 ||
- ssh_digest_update(hashctx, kex->session_id,
- kex->session_id_len) != 0 ||
+ ssh_digest_update_buffer(hashctx, kex->session_id) != 0 ||
ssh_digest_final(hashctx, digest, mdsz) != 0) {
r = SSH_ERR_LIBCRYPTO_ERROR;
- error("%s: KEX hash failed", __func__);
+ error_f("KEX hash failed");
goto out;
}
ssh_digest_free(hashctx);
@@ -1035,7 +1036,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
ssh_digest_update(hashctx, hash, hashlen) != 0 ||
ssh_digest_update(hashctx, digest, have) != 0 ||
ssh_digest_final(hashctx, digest + have, mdsz) != 0) {
- error("%s: KDF failed", __func__);
+ error_f("KDF failed");
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
@@ -1066,12 +1067,16 @@ kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen,
int r;
/* save initial hash as session id */
- if (kex->session_id == NULL) {
- kex->session_id_len = hashlen;
- kex->session_id = malloc(kex->session_id_len);
- if (kex->session_id == NULL)
- return SSH_ERR_ALLOC_FAIL;
- memcpy(kex->session_id, hash, kex->session_id_len);
+ if ((kex->flags & KEX_INITIAL) != 0) {
+ if (sshbuf_len(kex->session_id) != 0) {
+ error_f("already have session ID at kex");
+ return SSH_ERR_INTERNAL_ERROR;
+ }
+ if ((r = sshbuf_put(kex->session_id, hash, hashlen)) != 0)
+ return r;
+ } else if (sshbuf_len(kex->session_id) == 0) {
+ error_f("no session ID in rekex");
+ return SSH_ERR_INTERNAL_ERROR;
}
for (i = 0; i < NKEYS; i++) {
if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen,
@@ -1100,7 +1105,7 @@ kex_load_hostkey(struct ssh *ssh, struct sshkey **prvp, struct sshkey **pubp)
*prvp = NULL;
if (kex->load_host_public_key == NULL ||
kex->load_host_private_key == NULL) {
- error("%s: missing hostkey loader", __func__);
+ error_f("missing hostkey loader");
return SSH_ERR_INVALID_ARGUMENT;
}
*pubp = kex->load_host_public_key(kex->hostkey_type,
@@ -1118,7 +1123,7 @@ kex_verify_host_key(struct ssh *ssh, struct sshkey *server_host_key)
struct kex *kex = ssh->kex;
if (kex->verify_host_key == NULL) {
- error("%s: missing hostkey verifier", __func__);
+ error_f("missing hostkey verifier");
return SSH_ERR_INVALID_ARGUMENT;
}
if (server_host_key->type != kex->hostkey_type ||
@@ -1155,7 +1160,7 @@ send_error(struct ssh *ssh, char *msg)
msg, strlen(msg)) != strlen(msg) ||
atomicio(vwrite, ssh_packet_get_connection_out(ssh),
crnl, strlen(crnl)) != strlen(crnl))
- error("%s: write: %.100s", __func__, strerror(errno));
+ error_f("write: %.100s", strerror(errno));
}
/*
@@ -1183,11 +1188,11 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms,
if (version_addendum != NULL && *version_addendum == '\0')
version_addendum = NULL;
if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%.100s%s%s\r\n",
- PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION,
+ PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION,
version_addendum == NULL ? "" : " ",
version_addendum == NULL ? "" : version_addendum)) != 0) {
oerrno = errno;
- error("%s: sshbuf_putf: %s", __func__, ssh_err(r));
+ error_fr(r, "sshbuf_putf");
goto out;
}
@@ -1195,18 +1200,18 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms,
sshbuf_mutable_ptr(our_version),
sshbuf_len(our_version)) != sshbuf_len(our_version)) {
oerrno = errno;
- debug("%s: write: %.100s", __func__, strerror(errno));
+ debug_f("write: %.100s", strerror(errno));
r = SSH_ERR_SYSTEM_ERROR;
goto out;
}
if ((r = sshbuf_consume_end(our_version, 2)) != 0) { /* trim \r\n */
oerrno = errno;
- error("%s: sshbuf_consume_end: %s", __func__, ssh_err(r));
+ error_fr(r, "sshbuf_consume_end");
goto out;
}
our_version_string = sshbuf_dup_string(our_version);
if (our_version_string == NULL) {
- error("%s: sshbuf_dup_string failed", __func__);
+ error_f("sshbuf_dup_string failed");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
@@ -1217,8 +1222,8 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms,
if (n >= SSH_MAX_PRE_BANNER_LINES) {
send_error(ssh, "No SSH identification string "
"received.");
- error("%s: No SSH version received in first %u lines "
- "from server", __func__, SSH_MAX_PRE_BANNER_LINES);
+ error_f("No SSH version received in first %u lines "
+ "from server", SSH_MAX_PRE_BANNER_LINES);
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
@@ -1237,8 +1242,7 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms,
goto out;
} else if (r == -1) {
oerrno = errno;
- error("%s: %s",
- __func__, strerror(errno));
+ error_f("%s", strerror(errno));
r = SSH_ERR_SYSTEM_ERROR;
goto out;
}
@@ -1247,14 +1251,12 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms,
len = atomicio(read, ssh_packet_get_connection_in(ssh),
&c, 1);
if (len != 1 && errno == EPIPE) {
- error("%s: Connection closed by remote host",
- __func__);
+ error_f("Connection closed by remote host");
r = SSH_ERR_CONN_CLOSED;
goto out;
} else if (len != 1) {
oerrno = errno;
- error("%s: read: %.100s",
- __func__, strerror(errno));
+ error_f("read: %.100s", strerror(errno));
r = SSH_ERR_SYSTEM_ERROR;
goto out;
}
@@ -1265,18 +1267,17 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms,
if (c == '\n')
break;
if (c == '\0' || expect_nl) {
- error("%s: banner line contains invalid "
- "characters", __func__);
+ error_f("banner line contains invalid "
+ "characters");
goto invalid;
}
if ((r = sshbuf_put_u8(peer_version, c)) != 0) {
oerrno = errno;
- error("%s: sshbuf_put: %s",
- __func__, ssh_err(r));
+ error_fr(r, "sshbuf_put");
goto out;
}
if (sshbuf_len(peer_version) > SSH_MAX_BANNER_LEN) {
- error("%s: banner line too long", __func__);
+ error_f("banner line too long");
goto invalid;
}
}
@@ -1286,26 +1287,26 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms,
break;
/* If not, then just log the line and continue */
if ((cp = sshbuf_dup_string(peer_version)) == NULL) {
- error("%s: sshbuf_dup_string failed", __func__);
+ error_f("sshbuf_dup_string failed");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
/* Do not accept lines before the SSH ident from a client */
if (ssh->kex->server) {
- error("%s: client sent invalid protocol identifier "
- "\"%.256s\"", __func__, cp);
+ error_f("client sent invalid protocol identifier "
+ "\"%.256s\"", cp);
free(cp);
goto invalid;
}
- debug("%s: banner line %zu: %s", __func__, n, cp);
+ debug_f("banner line %zu: %s", n, cp);
free(cp);
}
peer_version_string = sshbuf_dup_string(peer_version);
if (peer_version_string == NULL)
- error("%s: sshbuf_dup_string failed", __func__);
+ error_f("sshbuf_dup_string failed");
/* XXX must be same size for sscanf */
if ((remote_version = calloc(1, sshbuf_len(peer_version))) == NULL) {
- error("%s: calloc failed", __func__);
+ error_f("calloc failed");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
@@ -1325,7 +1326,7 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms,
}
debug("Remote protocol version %d.%d, remote software version %.100s",
remote_major, remote_minor, remote_version);
- ssh->compat = compat_datafellows(remote_version);
+ compat_banner(ssh, remote_version);
mismatch = 0;
switch (remote_major) {
diff --git a/kex.h b/kex.h
index a5ae6ac05..9605ed528 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.h,v 1.109 2019/09/06 05:23:55 djm Exp $ */
+/* $OpenBSD: kex.h,v 1.114 2021/01/31 22:55:29 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -62,7 +62,7 @@
#define KEX_ECDH_SHA2_NISTP521 "ecdh-sha2-nistp521"
#define KEX_CURVE25519_SHA256 "curve25519-sha256"
#define KEX_CURVE25519_SHA256_OLD "curve25519-sha256@libssh.org"
-#define KEX_SNTRUP4591761X25519_SHA512 "sntrup4591761x25519-sha512@tinyssh.org"
+#define KEX_SNTRUP761X25519_SHA512 "sntrup761x25519-sha512@openssh.com"
#define COMP_NONE 0
/* pre-auth compression (COMP_ZLIB) is only supported in the client */
@@ -101,7 +101,7 @@ enum kex_exchange {
KEX_DH_GEX_SHA256,
KEX_ECDH_SHA2,
KEX_C25519_SHA256,
- KEX_KEM_SNTRUP4591761X25519_SHA512,
+ KEX_KEM_SNTRUP761X25519_SHA512,
KEX_MAX
};
@@ -132,8 +132,6 @@ struct newkeys {
struct ssh;
struct kex {
- u_char *session_id;
- size_t session_id_len;
struct newkeys *newkeys[MODE_MAX];
u_int we_need;
u_int dh_need;
@@ -149,6 +147,7 @@ struct kex {
struct sshbuf *peer;
struct sshbuf *client_version;
struct sshbuf *server_version;
+ struct sshbuf *session_id;
sig_atomic_t done;
u_int flags;
int hash_alg;
@@ -168,7 +167,7 @@ struct kex {
const EC_GROUP *ec_group; /* ECDH */
u_char c25519_client_key[CURVE25519_SIZE]; /* 25519 + KEM */
u_char c25519_client_pubkey[CURVE25519_SIZE]; /* 25519 */
- u_char sntrup4591761_client_key[crypto_kem_sntrup4591761_SECRETKEYBYTES]; /* KEM */
+ u_char sntrup761_client_key[crypto_kem_sntrup761_SECRETKEYBYTES]; /* KEM */
struct sshbuf *client_pub;
};
@@ -194,6 +193,7 @@ int kex_verify_host_key(struct ssh *, struct sshkey *);
int kex_send_kexinit(struct ssh *);
int kex_input_kexinit(int, u_int32_t, struct ssh *);
int kex_input_ext_info(int, u_int32_t, struct ssh *);
+int kex_protocol_error(int, u_int32_t, struct ssh *);
int kex_derive_keys(struct ssh *, u_char *, u_int, const struct sshbuf *);
int kex_send_newkeys(struct ssh *);
int kex_start_rekex(struct ssh *);
@@ -218,10 +218,10 @@ int kex_c25519_enc(struct kex *, const struct sshbuf *, struct sshbuf **,
struct sshbuf **);
int kex_c25519_dec(struct kex *, const struct sshbuf *, struct sshbuf **);
-int kex_kem_sntrup4591761x25519_keypair(struct kex *);
-int kex_kem_sntrup4591761x25519_enc(struct kex *, const struct sshbuf *,
+int kex_kem_sntrup761x25519_keypair(struct kex *);
+int kex_kem_sntrup761x25519_enc(struct kex *, const struct sshbuf *,
struct sshbuf **, struct sshbuf **);
-int kex_kem_sntrup4591761x25519_dec(struct kex *, const struct sshbuf *,
+int kex_kem_sntrup761x25519_dec(struct kex *, const struct sshbuf *,
struct sshbuf **);
int kex_dh_keygen(struct kex *);
diff --git a/kexdh.c b/kexdh.c
index 67133e339..c1084f214 100644
--- a/kexdh.c
+++ b/kexdh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexdh.c,v 1.32 2019/01/21 10:40:11 djm Exp $ */
+/* $OpenBSD: kexdh.c,v 1.34 2020/12/04 02:29:25 djm Exp $ */
/*
* Copyright (c) 2019 Markus Friedl. All rights reserved.
*
@@ -29,9 +29,9 @@
#include <sys/types.h>
-#include <signal.h>
#include <stdio.h>
#include <string.h>
+#include <signal.h>
#include "openbsd-compat/openssl-compat.h"
#include <openssl/dh.h>
@@ -42,6 +42,7 @@
#include "digest.h"
#include "ssherr.h"
#include "dh.h"
+#include "log.h"
int
kex_dh_keygen(struct kex *kex)
@@ -193,6 +194,7 @@ kex_dh_dec(struct kex *kex, const struct sshbuf *dh_blob,
*shared_secretp = buf;
buf = NULL;
out:
+ BN_free(dh_pub);
DH_free(kex->dh);
kex->dh = NULL;
sshbuf_free(buf);
diff --git a/kexgen.c b/kexgen.c
index 69348b964..bde28053d 100644
--- a/kexgen.c
+++ b/kexgen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexgen.c,v 1.4 2019/11/25 00:51:37 djm Exp $ */
+/* $OpenBSD: kexgen.c,v 1.7 2021/04/03 06:18:40 djm Exp $ */
/*
* Copyright (c) 2019 Markus Friedl. All rights reserved.
*
@@ -117,8 +117,8 @@ kex_gen_client(struct ssh *ssh)
case KEX_C25519_SHA256:
r = kex_c25519_keypair(kex);
break;
- case KEX_KEM_SNTRUP4591761X25519_SHA512:
- r = kex_kem_sntrup4591761x25519_keypair(kex);
+ case KEX_KEM_SNTRUP761X25519_SHA512:
+ r = kex_kem_sntrup761x25519_keypair(kex);
break;
default:
r = SSH_ERR_INVALID_ARGUMENT;
@@ -148,6 +148,9 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh)
size_t slen, hashlen;
int r;
+ debug("SSH2_MSG_KEX_ECDH_REPLY received");
+ ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &kex_protocol_error);
+
/* hostkey */
if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0)
goto out;
@@ -185,8 +188,8 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh)
case KEX_C25519_SHA256:
r = kex_c25519_dec(kex, server_blob, &shared_secret);
break;
- case KEX_KEM_SNTRUP4591761X25519_SHA512:
- r = kex_kem_sntrup4591761x25519_dec(kex, server_blob,
+ case KEX_KEM_SNTRUP761X25519_SHA512:
+ r = kex_kem_sntrup761x25519_dec(kex, server_blob,
&shared_secret);
break;
default:
@@ -220,8 +223,8 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh)
out:
explicit_bzero(hash, sizeof(hash));
explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key));
- explicit_bzero(kex->sntrup4591761_client_key,
- sizeof(kex->sntrup4591761_client_key));
+ explicit_bzero(kex->sntrup761_client_key,
+ sizeof(kex->sntrup761_client_key));
sshbuf_free(server_host_key_blob);
free(signature);
sshbuf_free(tmp);
@@ -254,6 +257,9 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh)
size_t slen, hashlen;
int r;
+ debug("SSH2_MSG_KEX_ECDH_INIT received");
+ ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_INIT, &kex_protocol_error);
+
if ((r = kex_load_hostkey(ssh, &server_host_private,
&server_host_public)) != 0)
goto out;
@@ -282,8 +288,8 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh)
r = kex_c25519_enc(kex, client_pubkey, &server_pubkey,
&shared_secret);
break;
- case KEX_KEM_SNTRUP4591761X25519_SHA512:
- r = kex_kem_sntrup4591761x25519_enc(kex, client_pubkey,
+ case KEX_KEM_SNTRUP761X25519_SHA512:
+ r = kex_kem_sntrup761x25519_enc(kex, client_pubkey,
&server_pubkey, &shared_secret);
break;
default:
@@ -316,7 +322,7 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh)
/* sign H */
if ((r = kex->sign(ssh, server_host_private, server_host_public,
- &signature, &slen, hash, hashlen, kex->hostkey_alg)) != 0)
+ &signature, &slen, hash, hashlen, kex->hostkey_alg)) != 0)
goto out;
/* send server hostkey, ECDH pubkey 'Q_S' and signed H */
diff --git a/kexgexc.c b/kexgexc.c
index 323a659b7..4a2e741d8 100644
--- a/kexgexc.c
+++ b/kexgexc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexgexc.c,v 1.35 2019/11/25 00:51:37 djm Exp $ */
+/* $OpenBSD: kexgexc.c,v 1.37 2021/01/31 22:55:29 djm Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -68,7 +68,7 @@ kexgex_client(struct ssh *ssh)
kex->min = DH_GRP_MIN;
kex->max = DH_GRP_MAX;
kex->nbits = nbits;
- if (datafellows & SSH_BUG_DHGEX_LARGE)
+ if (ssh->compat & SSH_BUG_DHGEX_LARGE)
kex->nbits = MINIMUM(kex->nbits, 4096);
/* New GEX request */
if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST)) != 0 ||
@@ -83,6 +83,7 @@ kexgex_client(struct ssh *ssh)
fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n",
kex->min, kex->nbits, kex->max);
#endif
+ debug("expecting SSH2_MSG_KEX_DH_GEX_GROUP");
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP,
&input_kex_dh_gex_group);
r = 0;
@@ -98,7 +99,8 @@ input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh)
const BIGNUM *pub_key;
int r, bits;
- debug("got SSH2_MSG_KEX_DH_GEX_GROUP");
+ debug("SSH2_MSG_KEX_DH_GEX_GROUP received");
+ ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, &kex_protocol_error);
if ((r = sshpkt_get_bignum2(ssh, &p)) != 0 ||
(r = sshpkt_get_bignum2(ssh, &g)) != 0 ||
@@ -130,7 +132,7 @@ input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh)
BN_print_fp(stderr, pub_key);
fprintf(stderr, "\n");
#endif
- ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, NULL);
+ debug("expecting SSH2_MSG_KEX_DH_GEX_REPLY");
ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, &input_kex_dh_gex_reply);
r = 0;
out:
@@ -153,7 +155,9 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh)
size_t slen, hashlen;
int r;
- debug("got SSH2_MSG_KEX_DH_GEX_REPLY");
+ debug("SSH2_MSG_KEX_DH_GEX_REPLY received");
+ ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, &kex_protocol_error);
+
/* key, cert */
if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0)
goto out;
diff --git a/kexgexs.c b/kexgexs.c
index 8ee3aaccb..f0fbcb912 100644
--- a/kexgexs.c
+++ b/kexgexs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexgexs.c,v 1.42 2019/01/23 00:30:41 djm Exp $ */
+/* $OpenBSD: kexgexs.c,v 1.43 2021/01/31 22:55:29 djm Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -77,6 +77,8 @@ input_kex_dh_gex_request(int type, u_int32_t seq, struct ssh *ssh)
const BIGNUM *dh_p, *dh_g;
debug("SSH2_MSG_KEX_DH_GEX_REQUEST received");
+ ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REQUEST, &kex_protocol_error);
+
if ((r = sshpkt_get_u32(ssh, &min)) != 0 ||
(r = sshpkt_get_u32(ssh, &nbits)) != 0 ||
(r = sshpkt_get_u32(ssh, &max)) != 0 ||
@@ -136,6 +138,9 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh)
size_t slen, hashlen;
int r;
+ debug("SSH2_MSG_KEX_DH_GEX_INIT received");
+ ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_INIT, &kex_protocol_error);
+
if ((r = kex_load_hostkey(ssh, &server_host_private,
&server_host_public)) != 0)
goto out;
diff --git a/kexsntrup4591761x25519.c b/kexsntrup761x25519.c
index 3b9b664f8..e3007fa29 100644
--- a/kexsntrup4591761x25519.c
+++ b/kexsntrup761x25519.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexsntrup4591761x25519.c,v 1.3 2019/01/21 10:40:11 djm Exp $ */
+/* $OpenBSD: kexsntrup761x25519.c,v 1.1 2020/12/29 00:59:15 djm Exp $ */
/*
* Copyright (c) 2019 Markus Friedl. All rights reserved.
*
@@ -25,6 +25,8 @@
#include "includes.h"
+#ifdef USE_SNTRUP761X25519
+
#include <sys/types.h>
#include <stdio.h>
@@ -38,7 +40,7 @@
#include "ssherr.h"
int
-kex_kem_sntrup4591761x25519_keypair(struct kex *kex)
+kex_kem_sntrup761x25519_keypair(struct kex *kex)
{
struct sshbuf *buf = NULL;
u_char *cp = NULL;
@@ -47,15 +49,15 @@ kex_kem_sntrup4591761x25519_keypair(struct kex *kex)
if ((buf = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
- need = crypto_kem_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE;
+ need = crypto_kem_sntrup761_PUBLICKEYBYTES + CURVE25519_SIZE;
if ((r = sshbuf_reserve(buf, need, &cp)) != 0)
goto out;
- crypto_kem_sntrup4591761_keypair(cp, kex->sntrup4591761_client_key);
+ crypto_kem_sntrup761_keypair(cp, kex->sntrup761_client_key);
#ifdef DEBUG_KEXECDH
- dump_digest("client public key sntrup4591761:", cp,
- crypto_kem_sntrup4591761_PUBLICKEYBYTES);
+ dump_digest("client public key sntrup761:", cp,
+ crypto_kem_sntrup761_PUBLICKEYBYTES);
#endif
- cp += crypto_kem_sntrup4591761_PUBLICKEYBYTES;
+ cp += crypto_kem_sntrup761_PUBLICKEYBYTES;
kexc25519_keygen(kex->c25519_client_key, cp);
#ifdef DEBUG_KEXECDH
dump_digest("client public key c25519:", cp, CURVE25519_SIZE);
@@ -68,7 +70,7 @@ kex_kem_sntrup4591761x25519_keypair(struct kex *kex)
}
int
-kex_kem_sntrup4591761x25519_enc(struct kex *kex,
+kex_kem_sntrup761x25519_enc(struct kex *kex,
const struct sshbuf *client_blob, struct sshbuf **server_blobp,
struct sshbuf **shared_secretp)
{
@@ -85,17 +87,17 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex,
*shared_secretp = NULL;
/* client_blob contains both KEM and ECDH client pubkeys */
- need = crypto_kem_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE;
+ need = crypto_kem_sntrup761_PUBLICKEYBYTES + CURVE25519_SIZE;
if (sshbuf_len(client_blob) != need) {
r = SSH_ERR_SIGNATURE_INVALID;
goto out;
}
client_pub = sshbuf_ptr(client_blob);
#ifdef DEBUG_KEXECDH
- dump_digest("client public key sntrup4591761:", client_pub,
- crypto_kem_sntrup4591761_PUBLICKEYBYTES);
+ dump_digest("client public key sntrup761:", client_pub,
+ crypto_kem_sntrup761_PUBLICKEYBYTES);
dump_digest("client public key 25519:",
- client_pub + crypto_kem_sntrup4591761_PUBLICKEYBYTES,
+ client_pub + crypto_kem_sntrup761_PUBLICKEYBYTES,
CURVE25519_SIZE);
#endif
/* allocate buffer for concatenation of KEM key and ECDH shared key */
@@ -104,7 +106,7 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex,
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((r = sshbuf_reserve(buf, crypto_kem_sntrup4591761_BYTES,
+ if ((r = sshbuf_reserve(buf, crypto_kem_sntrup761_BYTES,
&kem_key)) != 0)
goto out;
/* allocate space for encrypted KEM key and ECDH pub key */
@@ -112,16 +114,16 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex,
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE;
+ need = crypto_kem_sntrup761_CIPHERTEXTBYTES + CURVE25519_SIZE;
if ((r = sshbuf_reserve(server_blob, need, &ciphertext)) != 0)
goto out;
/* generate and encrypt KEM key with client key */
- crypto_kem_sntrup4591761_enc(ciphertext, kem_key, client_pub);
+ crypto_kem_sntrup761_enc(ciphertext, kem_key, client_pub);
/* generate ECDH key pair, store server pubkey after ciphertext */
- server_pub = ciphertext + crypto_kem_sntrup4591761_CIPHERTEXTBYTES;
+ server_pub = ciphertext + crypto_kem_sntrup761_CIPHERTEXTBYTES;
kexc25519_keygen(server_key, server_pub);
/* append ECDH shared key */
- client_pub += crypto_kem_sntrup4591761_PUBLICKEYBYTES;
+ client_pub += crypto_kem_sntrup761_PUBLICKEYBYTES;
if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 1)) < 0)
goto out;
if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0)
@@ -129,7 +131,7 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex,
#ifdef DEBUG_KEXECDH
dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE);
dump_digest("server cipher text:", ciphertext,
- crypto_kem_sntrup4591761_CIPHERTEXTBYTES);
+ crypto_kem_sntrup761_CIPHERTEXTBYTES);
dump_digest("server kem key:", kem_key, sizeof(kem_key));
dump_digest("concatenation of KEM key and ECDH shared key:",
sshbuf_ptr(buf), sshbuf_len(buf));
@@ -155,7 +157,7 @@ kex_kem_sntrup4591761x25519_enc(struct kex *kex,
}
int
-kex_kem_sntrup4591761x25519_dec(struct kex *kex,
+kex_kem_sntrup761x25519_dec(struct kex *kex,
const struct sshbuf *server_blob, struct sshbuf **shared_secretp)
{
struct sshbuf *buf = NULL;
@@ -167,16 +169,16 @@ kex_kem_sntrup4591761x25519_dec(struct kex *kex,
*shared_secretp = NULL;
- need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE;
+ need = crypto_kem_sntrup761_CIPHERTEXTBYTES + CURVE25519_SIZE;
if (sshbuf_len(server_blob) != need) {
r = SSH_ERR_SIGNATURE_INVALID;
goto out;
}
ciphertext = sshbuf_ptr(server_blob);
- server_pub = ciphertext + crypto_kem_sntrup4591761_CIPHERTEXTBYTES;
+ server_pub = ciphertext + crypto_kem_sntrup761_CIPHERTEXTBYTES;
#ifdef DEBUG_KEXECDH
dump_digest("server cipher text:", ciphertext,
- crypto_kem_sntrup4591761_CIPHERTEXTBYTES);
+ crypto_kem_sntrup761_CIPHERTEXTBYTES);
dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE);
#endif
/* hash concatenation of KEM key and ECDH shared key */
@@ -184,18 +186,18 @@ kex_kem_sntrup4591761x25519_dec(struct kex *kex,
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((r = sshbuf_reserve(buf, crypto_kem_sntrup4591761_BYTES,
+ if ((r = sshbuf_reserve(buf, crypto_kem_sntrup761_BYTES,
&kem_key)) != 0)
goto out;
- decoded = crypto_kem_sntrup4591761_dec(kem_key, ciphertext,
- kex->sntrup4591761_client_key);
+ decoded = crypto_kem_sntrup761_dec(kem_key, ciphertext,
+ kex->sntrup761_client_key);
if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub,
buf, 1)) < 0)
goto out;
if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0)
goto out;
#ifdef DEBUG_KEXECDH
- dump_digest("client kem key:", kem_key, sizeof(kem_key));
+ dump_digest("client kem key:", kem_key, crypto_kem_sntrup761_BYTES);
dump_digest("concatenation of KEM key and ECDH shared key:",
sshbuf_ptr(buf), sshbuf_len(buf));
#endif
@@ -217,3 +219,33 @@ kex_kem_sntrup4591761x25519_dec(struct kex *kex,
sshbuf_free(buf);
return r;
}
+
+#else
+
+#include "ssherr.h"
+
+struct kex;
+struct sshbuf;
+struct sshkey;
+
+int
+kex_kem_sntrup761x25519_keypair(struct kex *kex)
+{
+ return SSH_ERR_SIGN_ALG_UNSUPPORTED;
+}
+
+int
+kex_kem_sntrup761x25519_enc(struct kex *kex,
+ const struct sshbuf *client_blob, struct sshbuf **server_blobp,
+ struct sshbuf **shared_secretp)
+{
+ return SSH_ERR_SIGN_ALG_UNSUPPORTED;
+}
+
+int
+kex_kem_sntrup761x25519_dec(struct kex *kex,
+ const struct sshbuf *server_blob, struct sshbuf **shared_secretp)
+{
+ return SSH_ERR_SIGN_ALG_UNSUPPORTED;
+}
+#endif /* USE_SNTRUP761X25519 */
diff --git a/krl.c b/krl.c
index c431f7047..17b88edde 100644
--- a/krl.c
+++ b/krl.c
@@ -14,7 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $OpenBSD: krl.c,v 1.50 2020/04/03 05:48:57 djm Exp $ */
+/* $OpenBSD: krl.c,v 1.53 2021/06/04 06:19:07 djm Exp $ */
#include "includes.h"
@@ -44,7 +44,7 @@
/* #define DEBUG_KRL */
#ifdef DEBUG_KRL
-# define KRL_DBG(x) debug3 x
+# define KRL_DBG(x) debug3_f x
#else
# define KRL_DBG(x)
#endif
@@ -61,7 +61,7 @@ struct revoked_serial {
};
static int serial_cmp(struct revoked_serial *a, struct revoked_serial *b);
RB_HEAD(revoked_serial_tree, revoked_serial);
-RB_GENERATE_STATIC(revoked_serial_tree, revoked_serial, tree_entry, serial_cmp);
+RB_GENERATE_STATIC(revoked_serial_tree, revoked_serial, tree_entry, serial_cmp)
/* Tree of key IDs */
struct revoked_key_id {
@@ -70,7 +70,7 @@ struct revoked_key_id {
};
static int key_id_cmp(struct revoked_key_id *a, struct revoked_key_id *b);
RB_HEAD(revoked_key_id_tree, revoked_key_id);
-RB_GENERATE_STATIC(revoked_key_id_tree, revoked_key_id, tree_entry, key_id_cmp);
+RB_GENERATE_STATIC(revoked_key_id_tree, revoked_key_id, tree_entry, key_id_cmp)
/* Tree of blobs (used for keys and fingerprints) */
struct revoked_blob {
@@ -80,7 +80,7 @@ struct revoked_blob {
};
static int blob_cmp(struct revoked_blob *a, struct revoked_blob *b);
RB_HEAD(revoked_blob_tree, revoked_blob);
-RB_GENERATE_STATIC(revoked_blob_tree, revoked_blob, tree_entry, blob_cmp);
+RB_GENERATE_STATIC(revoked_blob_tree, revoked_blob, tree_entry, blob_cmp)
/* Tracks revoked certs for a single CA */
struct revoked_certs {
@@ -241,8 +241,7 @@ revoked_certs_for_ca_key(struct ssh_krl *krl, const struct sshkey *ca_key,
RB_INIT(&rc->revoked_serials);
RB_INIT(&rc->revoked_key_ids);
TAILQ_INSERT_TAIL(&krl->revoked_certs, rc, entry);
- KRL_DBG(("%s: new CA %s", __func__,
- ca_key == NULL ? "*" : sshkey_type(ca_key)));
+ KRL_DBG(("new CA %s", ca_key == NULL ? "*" : sshkey_type(ca_key)));
*rcp = rc;
return 0;
}
@@ -252,7 +251,7 @@ insert_serial_range(struct revoked_serial_tree *rt, u_int64_t lo, u_int64_t hi)
{
struct revoked_serial rs, *ers, *crs, *irs;
- KRL_DBG(("%s: insert %llu:%llu", __func__, lo, hi));
+ KRL_DBG(("insert %llu:%llu", lo, hi));
memset(&rs, 0, sizeof(rs));
rs.lo = lo;
rs.hi = hi;
@@ -264,15 +263,14 @@ insert_serial_range(struct revoked_serial_tree *rt, u_int64_t lo, u_int64_t hi)
memcpy(irs, &rs, sizeof(*irs));
ers = RB_INSERT(revoked_serial_tree, rt, irs);
if (ers != NULL) {
- KRL_DBG(("%s: bad: ers != NULL", __func__));
+ KRL_DBG(("bad: ers != NULL"));
/* Shouldn't happen */
free(irs);
return SSH_ERR_INTERNAL_ERROR;
}
ers = irs;
} else {
- KRL_DBG(("%s: overlap found %llu:%llu", __func__,
- ers->lo, ers->hi));
+ KRL_DBG(("overlap found %llu:%llu", ers->lo, ers->hi));
/*
* The inserted entry overlaps an existing one. Grow the
* existing entry.
@@ -290,33 +288,31 @@ insert_serial_range(struct revoked_serial_tree *rt, u_int64_t lo, u_int64_t hi)
/* Check predecessors */
while ((crs = RB_PREV(revoked_serial_tree, rt, ers)) != NULL) {
- KRL_DBG(("%s: pred %llu:%llu", __func__, crs->lo, crs->hi));
+ KRL_DBG(("pred %llu:%llu", crs->lo, crs->hi));
if (ers->lo != 0 && crs->hi < ers->lo - 1)
break;
/* This entry overlaps. */
if (crs->lo < ers->lo) {
ers->lo = crs->lo;
- KRL_DBG(("%s: pred extend %llu:%llu", __func__,
- ers->lo, ers->hi));
+ KRL_DBG(("pred extend %llu:%llu", ers->lo, ers->hi));
}
RB_REMOVE(revoked_serial_tree, rt, crs);
free(crs);
}
/* Check successors */
while ((crs = RB_NEXT(revoked_serial_tree, rt, ers)) != NULL) {
- KRL_DBG(("%s: succ %llu:%llu", __func__, crs->lo, crs->hi));
+ KRL_DBG(("succ %llu:%llu", crs->lo, crs->hi));
if (ers->hi != (u_int64_t)-1 && crs->lo > ers->hi + 1)
break;
/* This entry overlaps. */
if (crs->hi > ers->hi) {
ers->hi = crs->hi;
- KRL_DBG(("%s: succ extend %llu:%llu", __func__,
- ers->lo, ers->hi));
+ KRL_DBG(("succ extend %llu:%llu", ers->lo, ers->hi));
}
RB_REMOVE(revoked_serial_tree, rt, crs);
free(crs);
}
- KRL_DBG(("%s: done, final %llu:%llu", __func__, ers->lo, ers->hi));
+ KRL_DBG(("done, final %llu:%llu", ers->lo, ers->hi));
return 0;
}
@@ -352,7 +348,7 @@ ssh_krl_revoke_cert_by_key_id(struct ssh_krl *krl, const struct sshkey *ca_key,
if ((r = revoked_certs_for_ca_key(krl, ca_key, &rc, 1)) != 0)
return r;
- KRL_DBG(("%s: revoke %s", __func__, key_id));
+ KRL_DBG(("revoke %s", key_id));
if ((rki = calloc(1, sizeof(*rki))) == NULL ||
(rki->key_id = strdup(key_id)) == NULL) {
free(rki);
@@ -411,7 +407,7 @@ ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const struct sshkey *key)
size_t len;
int r;
- debug3("%s: revoke type %s", __func__, sshkey_type(key));
+ debug3_f("revoke type %s", sshkey_type(key));
if ((r = plain_key_blob(key, &blob, &len)) != 0)
return r;
return revoke_blob(&krl->revoked_keys, blob, len);
@@ -437,7 +433,7 @@ revoke_by_hash(struct revoked_blob_tree *target, const u_char *p, size_t len)
int
ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const u_char *p, size_t len)
{
- debug3("%s: revoke by sha1", __func__);
+ debug3_f("revoke by sha1");
if (len != 20)
return SSH_ERR_INVALID_FORMAT;
return revoke_by_hash(&krl->revoked_sha1s, p, len);
@@ -446,7 +442,7 @@ ssh_krl_revoke_key_sha1(struct ssh_krl *krl, const u_char *p, size_t len)
int
ssh_krl_revoke_key_sha256(struct ssh_krl *krl, const u_char *p, size_t len)
{
- debug3("%s: revoke by sha256", __func__);
+ debug3_f("revoke by sha256");
if (len != 32)
return SSH_ERR_INVALID_FORMAT;
return revoke_by_hash(&krl->revoked_sha256s, p, len);
@@ -542,9 +538,9 @@ choose_next_state(int current_state, u_int64_t contig, int final,
*force_new_section = 1;
cost = cost_bitmap_restart;
}
- KRL_DBG(("%s: contig %llu last_gap %llu next_gap %llu final %d, costs:"
+ KRL_DBG(("contig %llu last_gap %llu next_gap %llu final %d, costs:"
"list %llu range %llu bitmap %llu new bitmap %llu, "
- "selected 0x%02x%s", __func__, (long long unsigned)contig,
+ "selected 0x%02x%s", (long long unsigned)contig,
(long long unsigned)last_gap, (long long unsigned)next_gap, final,
(long long unsigned)cost_list, (long long unsigned)cost_range,
(long long unsigned)cost_bitmap,
@@ -602,7 +598,7 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf)
for (rs = RB_MIN(revoked_serial_tree, &rc->revoked_serials);
rs != NULL;
rs = RB_NEXT(revoked_serial_tree, &rc->revoked_serials, rs)) {
- KRL_DBG(("%s: serial %llu:%llu state 0x%02x", __func__,
+ KRL_DBG(("serial %llu:%llu state 0x%02x",
(long long unsigned)rs->lo, (long long unsigned)rs->hi,
state));
@@ -622,7 +618,7 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf)
*/
if (state != 0 && (force_new_sect || next_state != state ||
state == KRL_SECTION_CERT_SERIAL_RANGE)) {
- KRL_DBG(("%s: finish state 0x%02x", __func__, state));
+ KRL_DBG(("finish state 0x%02x", state));
switch (state) {
case KRL_SECTION_CERT_SERIAL_LIST:
case KRL_SECTION_CERT_SERIAL_RANGE:
@@ -642,7 +638,7 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf)
/* If we are starting a new section then prepare it now */
if (next_state != state || force_new_sect) {
- KRL_DBG(("%s: start state 0x%02x", __func__,
+ KRL_DBG(("start state 0x%02x",
next_state));
state = next_state;
sshbuf_reset(sect);
@@ -678,7 +674,7 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf)
break;
case KRL_SECTION_CERT_SERIAL_BITMAP:
if (rs->lo - bitmap_start > INT_MAX) {
- error("%s: insane bitmap gap", __func__);
+ error_f("insane bitmap gap");
goto out;
}
for (i = 0; i < contig; i++) {
@@ -694,8 +690,7 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf)
}
/* Flush the remaining section, if any */
if (state != 0) {
- KRL_DBG(("%s: serial final flush for state 0x%02x",
- __func__, state));
+ KRL_DBG(("serial final flush for state 0x%02x", state));
switch (state) {
case KRL_SECTION_CERT_SERIAL_LIST:
case KRL_SECTION_CERT_SERIAL_RANGE:
@@ -711,12 +706,12 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf)
(r = sshbuf_put_stringb(buf, sect)) != 0)
goto out;
}
- KRL_DBG(("%s: serial done ", __func__));
+ KRL_DBG(("serial done "));
/* Now output a section for any revocations by key ID */
sshbuf_reset(sect);
RB_FOREACH(rki, revoked_key_id_tree, &rc->revoked_key_ids) {
- KRL_DBG(("%s: key ID %s", __func__, rki->key_id));
+ KRL_DBG(("key ID %s", rki->key_id));
if ((r = sshbuf_put_cstring(sect, rki->key_id)) != 0)
goto out;
}
@@ -772,7 +767,7 @@ ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf,
/* Finally, output sections for revocations by public key/hash */
sshbuf_reset(sect);
RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_keys) {
- KRL_DBG(("%s: key len %zu ", __func__, rb->len));
+ KRL_DBG(("key len %zu ", rb->len));
if ((r = sshbuf_put_string(sect, rb->blob, rb->len)) != 0)
goto out;
}
@@ -783,7 +778,7 @@ ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf,
}
sshbuf_reset(sect);
RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha1s) {
- KRL_DBG(("%s: hash len %zu ", __func__, rb->len));
+ KRL_DBG(("hash len %zu ", rb->len));
if ((r = sshbuf_put_string(sect, rb->blob, rb->len)) != 0)
goto out;
}
@@ -795,7 +790,7 @@ ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf,
}
sshbuf_reset(sect);
RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_sha256s) {
- KRL_DBG(("%s: hash len %zu ", __func__, rb->len));
+ KRL_DBG(("hash len %zu ", rb->len));
if ((r = sshbuf_put_string(sect, rb->blob, rb->len)) != 0)
goto out;
}
@@ -807,16 +802,16 @@ ssh_krl_to_blob(struct ssh_krl *krl, struct sshbuf *buf,
}
for (i = 0; i < nsign_keys; i++) {
- KRL_DBG(("%s: signature key %s", __func__,
- sshkey_ssh_name(sign_keys[i])));
+ KRL_DBG(("sig key %s", sshkey_ssh_name(sign_keys[i])));
if ((r = sshbuf_put_u8(buf, KRL_SECTION_SIGNATURE)) != 0 ||
(r = sshkey_puts(sign_keys[i], buf)) != 0)
goto out;
-
+ /* XXX support sk-* keys */
if ((r = sshkey_sign(sign_keys[i], &sblob, &slen,
- sshbuf_ptr(buf), sshbuf_len(buf), NULL, NULL, 0)) != 0)
+ sshbuf_ptr(buf), sshbuf_len(buf), NULL, NULL,
+ NULL, 0)) != 0)
goto out;
- KRL_DBG(("%s: signature sig len %zu", __func__, slen));
+ KRL_DBG(("signature sig len %zu", slen));
if ((r = sshbuf_put_string(buf, sblob, slen)) != 0)
goto out;
}
@@ -873,7 +868,7 @@ parse_revoked_certs(struct sshbuf *buf, struct ssh_krl *krl)
if ((r = sshbuf_get_u8(buf, &type)) != 0 ||
(r = sshbuf_froms(buf, &subsect)) != 0)
goto out;
- KRL_DBG(("%s: subsection type 0x%02x", __func__, type));
+ KRL_DBG(("subsection type 0x%02x", type));
/* sshbuf_dump(subsect, stderr); */
switch (type) {
@@ -910,7 +905,7 @@ parse_revoked_certs(struct sshbuf *buf, struct ssh_krl *krl)
nbits = bitmap_nbits(bitmap);
for (serial = 0; serial < (u_int64_t)nbits; serial++) {
if (serial > 0 && serial_lo + serial == 0) {
- error("%s: bitmap wraps u64", __func__);
+ error_f("bitmap wraps u64");
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
@@ -969,7 +964,7 @@ blob_section(struct sshbuf *sect, struct revoked_blob_tree *target_tree,
if ((r = sshbuf_get_string(sect, &rdata, &rlen)) != 0)
return r;
if (expected_len != 0 && rlen != expected_len) {
- error("%s: bad length", __func__);
+ error_f("bad length");
free(rdata);
return SSH_ERR_INVALID_FORMAT;
}
@@ -1000,7 +995,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
*krlp = NULL;
if (sshbuf_len(buf) < sizeof(KRL_MAGIC) - 1 ||
memcmp(sshbuf_ptr(buf), KRL_MAGIC, sizeof(KRL_MAGIC) - 1) != 0) {
- debug3("%s: not a KRL", __func__);
+ debug3_f("not a KRL");
return SSH_ERR_KRL_BAD_MAGIC;
}
@@ -1013,7 +1008,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
goto out;
if ((krl = ssh_krl_init()) == NULL) {
- error("%s: alloc failed", __func__);
+ error_f("alloc failed");
goto out;
}
@@ -1050,7 +1045,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
if ((r = sshbuf_get_u8(copy, &type)) != 0 ||
(r = sshbuf_get_string_direct(copy, &blob, &blen)) != 0)
goto out;
- KRL_DBG(("%s: first pass, section 0x%02x", __func__, type));
+ KRL_DBG(("first pass, section 0x%02x", type));
if (type != KRL_SECTION_SIGNATURE) {
if (sig_seen) {
error("KRL contains non-signature section "
@@ -1126,7 +1121,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp,
if ((r = sshbuf_get_u8(copy, &type)) != 0 ||
(r = sshbuf_froms(copy, &sect)) != 0)
goto out;
- KRL_DBG(("%s: second pass, section 0x%02x", __func__, type));
+ KRL_DBG(("second pass, section 0x%02x", type));
switch (type) {
case KRL_SECTION_CERTIFICATES:
@@ -1229,7 +1224,7 @@ is_cert_revoked(const struct sshkey *key, struct revoked_certs *rc)
rki.key_id = key->cert->key_id;
erki = RB_FIND(revoked_key_id_tree, &rc->revoked_key_ids, &rki);
if (erki != NULL) {
- KRL_DBG(("%s: revoked by key ID", __func__));
+ KRL_DBG(("revoked by key ID"));
return SSH_ERR_KEY_REVOKED;
}
@@ -1244,7 +1239,7 @@ is_cert_revoked(const struct sshkey *key, struct revoked_certs *rc)
rs.lo = rs.hi = key->cert->serial;
ers = RB_FIND(revoked_serial_tree, &rc->revoked_serials, &rs);
if (ers != NULL) {
- KRL_DBG(("%s: revoked serial %llu matched %llu:%llu", __func__,
+ KRL_DBG(("revoked serial %llu matched %llu:%llu",
key->cert->serial, ers->lo, ers->hi));
return SSH_ERR_KEY_REVOKED;
}
@@ -1267,7 +1262,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key)
erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb);
free(rb.blob);
if (erb != NULL) {
- KRL_DBG(("%s: revoked by key SHA1", __func__));
+ KRL_DBG(("revoked by key SHA1"));
return SSH_ERR_KEY_REVOKED;
}
memset(&rb, 0, sizeof(rb));
@@ -1277,7 +1272,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key)
erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha256s, &rb);
free(rb.blob);
if (erb != NULL) {
- KRL_DBG(("%s: revoked by key SHA256", __func__));
+ KRL_DBG(("revoked by key SHA256"));
return SSH_ERR_KEY_REVOKED;
}
@@ -1288,7 +1283,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key)
erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb);
free(rb.blob);
if (erb != NULL) {
- KRL_DBG(("%s: revoked by explicit key", __func__));
+ KRL_DBG(("revoked by explicit key"));
return SSH_ERR_KEY_REVOKED;
}
@@ -1311,7 +1306,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key)
return r;
}
- KRL_DBG(("%s: %llu no match", __func__, key->cert->serial));
+ KRL_DBG(("%llu no match", key->cert->serial));
return 0;
}
@@ -1320,15 +1315,15 @@ ssh_krl_check_key(struct ssh_krl *krl, const struct sshkey *key)
{
int r;
- KRL_DBG(("%s: checking key", __func__));
+ KRL_DBG(("checking key"));
if ((r = is_key_revoked(krl, key)) != 0)
return r;
if (sshkey_is_cert(key)) {
- debug2("%s: checking CA key", __func__);
+ debug2_f("checking CA key");
if ((r = is_key_revoked(krl, key->cert->signature_key)) != 0)
return r;
}
- KRL_DBG(("%s: key okay", __func__));
+ KRL_DBG(("key okay"));
return 0;
}
@@ -1347,7 +1342,7 @@ ssh_krl_file_contains_key(const char *path, const struct sshkey *key)
}
if ((r = ssh_krl_from_blob(krlbuf, &krl, NULL, 0)) != 0)
goto out;
- debug2("%s: checking KRL %s", __func__, path);
+ debug2_f("checking KRL %s", path);
r = ssh_krl_check_key(krl, key);
out:
sshbuf_free(krlbuf);
@@ -1384,7 +1379,7 @@ krl_dump(struct ssh_krl *krl, FILE *f)
RB_FOREACH(rb, revoked_blob_tree, &krl->revoked_keys) {
if ((r = sshkey_from_blob(rb->blob, rb->len, &key)) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
- error("Parse key in KRL: %s", ssh_err(r));
+ error_r(r, "parse KRL key");
continue;
}
if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
diff --git a/log.c b/log.c
index d9c2d136c..99bf046a7 100644
--- a/log.c
+++ b/log.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.c,v 1.51 2018/07/27 12:03:17 markus Exp $ */
+/* $OpenBSD: log.c,v 1.60 2021/09/16 15:11:19 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -51,14 +51,17 @@
#endif
#include "log.h"
+#include "match.h"
static LogLevel log_level = SYSLOG_LEVEL_INFO;
static int log_on_stderr = 1;
static int log_stderr_fd = STDERR_FILENO;
static int log_facility = LOG_AUTH;
-static char *argv0;
+static const char *argv0;
static log_handler_fn *log_handler;
static void *log_handler_ctx;
+static char **log_verbose;
+static size_t nlog_verbose;
extern char *__progname;
@@ -157,96 +160,30 @@ log_level_name(LogLevel level)
return NULL;
}
-/* Error messages that should be logged. */
-
-void
-error(const char *fmt,...)
-{
- va_list args;
-
- va_start(args, fmt);
- do_log(SYSLOG_LEVEL_ERROR, fmt, args);
- va_end(args);
-}
-
-void
-sigdie(const char *fmt,...)
-{
-#ifdef DO_LOG_SAFE_IN_SIGHAND
- va_list args;
-
- va_start(args, fmt);
- do_log(SYSLOG_LEVEL_FATAL, fmt, args);
- va_end(args);
-#endif
- _exit(1);
-}
-
void
-logdie(const char *fmt,...)
+log_verbose_add(const char *s)
{
- va_list args;
-
- va_start(args, fmt);
- do_log(SYSLOG_LEVEL_INFO, fmt, args);
- va_end(args);
- cleanup_exit(255);
-}
-
-/* Log this message (information that usually should go to the log). */
-
-void
-logit(const char *fmt,...)
-{
- va_list args;
-
- va_start(args, fmt);
- do_log(SYSLOG_LEVEL_INFO, fmt, args);
- va_end(args);
-}
-
-/* More detailed messages (information that does not need to go to the log). */
-
-void
-verbose(const char *fmt,...)
-{
- va_list args;
-
- va_start(args, fmt);
- do_log(SYSLOG_LEVEL_VERBOSE, fmt, args);
- va_end(args);
-}
-
-/* Debugging messages that should not be logged during normal operation. */
-
-void
-debug(const char *fmt,...)
-{
- va_list args;
-
- va_start(args, fmt);
- do_log(SYSLOG_LEVEL_DEBUG1, fmt, args);
- va_end(args);
-}
-
-void
-debug2(const char *fmt,...)
-{
- va_list args;
-
- va_start(args, fmt);
- do_log(SYSLOG_LEVEL_DEBUG2, fmt, args);
- va_end(args);
+ char **tmp;
+
+ /* Ignore failures here */
+ if ((tmp = recallocarray(log_verbose, nlog_verbose, nlog_verbose + 1,
+ sizeof(*log_verbose))) != NULL) {
+ log_verbose = tmp;
+ if ((log_verbose[nlog_verbose] = strdup(s)) != NULL)
+ nlog_verbose++;
+ }
}
void
-debug3(const char *fmt,...)
+log_verbose_reset(void)
{
- va_list args;
+ size_t i;
- va_start(args, fmt);
- do_log(SYSLOG_LEVEL_DEBUG3, fmt, args);
- va_end(args);
+ for (i = 0; i < nlog_verbose; i++)
+ free(log_verbose[i]);
+ free(log_verbose);
+ log_verbose = NULL;
+ nlog_verbose = 0;
}
/*
@@ -254,7 +191,8 @@ debug3(const char *fmt,...)
*/
void
-log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
+log_init(const char *av0, LogLevel level, SyslogFacility facility,
+ int on_stderr)
{
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
struct syslog_data sdata = SYSLOG_DATA_INIT;
@@ -370,9 +308,17 @@ log_redirect_stderr_to(const char *logfile)
{
int fd;
+ if (logfile == NULL) {
+ if (log_stderr_fd != STDERR_FILENO) {
+ close(log_stderr_fd);
+ log_stderr_fd = STDERR_FILENO;
+ }
+ return;
+ }
+
if ((fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600)) == -1) {
fprintf(stderr, "Couldn't open logfile %s: %s\n", logfile,
- strerror(errno));
+ strerror(errno));
exit(1);
}
log_stderr_fd = fd;
@@ -387,18 +333,9 @@ set_log_handler(log_handler_fn *handler, void *ctx)
log_handler_ctx = ctx;
}
-void
-do_log2(LogLevel level, const char *fmt,...)
-{
- va_list args;
-
- va_start(args, fmt);
- do_log(level, fmt, args);
- va_end(args);
-}
-
-void
-do_log(LogLevel level, const char *fmt, va_list args)
+static void
+do_log(LogLevel level, int force, const char *suffix, const char *fmt,
+ va_list args)
{
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
struct syslog_data sdata = SYSLOG_DATA_INIT;
@@ -409,8 +346,9 @@ do_log(LogLevel level, const char *fmt, va_list args)
int pri = LOG_INFO;
int saved_errno = errno;
log_handler_fn *tmp_handler;
+ const char *progname = argv0 != NULL ? argv0 : __progname;
- if (level > log_level)
+ if (!force && level > log_level)
return;
switch (level) {
@@ -453,28 +391,110 @@ do_log(LogLevel level, const char *fmt, va_list args)
} else {
vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
}
+ if (suffix != NULL) {
+ snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", msgbuf, suffix);
+ strlcpy(msgbuf, fmtbuf, sizeof(msgbuf));
+ }
strnvis(fmtbuf, msgbuf, sizeof(fmtbuf),
log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS);
if (log_handler != NULL) {
/* Avoid recursion */
tmp_handler = log_handler;
log_handler = NULL;
- tmp_handler(level, fmtbuf, log_handler_ctx);
+ tmp_handler(level, force, fmtbuf, log_handler_ctx);
log_handler = tmp_handler;
} else if (log_on_stderr) {
- snprintf(msgbuf, sizeof msgbuf, "%.*s\r\n",
+ snprintf(msgbuf, sizeof msgbuf, "%s%s%.*s\r\n",
+ (log_on_stderr > 1) ? progname : "",
+ (log_on_stderr > 1) ? ": " : "",
(int)sizeof msgbuf - 3, fmtbuf);
(void)write(log_stderr_fd, msgbuf, strlen(msgbuf));
} else {
#if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT)
- openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata);
+ openlog_r(progname, LOG_PID, log_facility, &sdata);
syslog_r(pri, &sdata, "%.500s", fmtbuf);
closelog_r(&sdata);
#else
- openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility);
+ openlog(progname, LOG_PID, log_facility);
syslog(pri, "%.500s", fmtbuf);
closelog();
#endif
}
errno = saved_errno;
}
+
+void
+sshlog(const char *file, const char *func, int line, int showfunc,
+ LogLevel level, const char *suffix, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ sshlogv(file, func, line, showfunc, level, suffix, fmt, args);
+ va_end(args);
+}
+
+void
+sshlogdie(const char *file, const char *func, int line, int showfunc,
+ LogLevel level, const char *suffix, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ sshlogv(file, func, line, showfunc, SYSLOG_LEVEL_INFO,
+ suffix, fmt, args);
+ va_end(args);
+ cleanup_exit(255);
+}
+
+void
+sshsigdie(const char *file, const char *func, int line, int showfunc,
+ LogLevel level, const char *suffix, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ sshlogv(file, func, line, showfunc, SYSLOG_LEVEL_FATAL,
+ suffix, fmt, args);
+ va_end(args);
+ _exit(1);
+}
+
+void
+sshlogv(const char *file, const char *func, int line, int showfunc,
+ LogLevel level, const char *suffix, const char *fmt, va_list args)
+{
+ char tag[128], fmt2[MSGBUFSIZ + 128];
+ int forced = 0;
+ const char *cp;
+ size_t i;
+
+ snprintf(tag, sizeof(tag), "%.48s:%.48s():%d (pid=%ld)",
+ (cp = strrchr(file, '/')) == NULL ? file : cp + 1, func, line,
+ (long)getpid());
+ for (i = 0; i < nlog_verbose; i++) {
+ if (match_pattern_list(tag, log_verbose[i], 0) == 1) {
+ forced = 1;
+ break;
+ }
+ }
+
+ if (forced)
+ snprintf(fmt2, sizeof(fmt2), "%s: %s", tag, fmt);
+ else if (showfunc)
+ snprintf(fmt2, sizeof(fmt2), "%s: %s", func, fmt);
+ else
+ strlcpy(fmt2, fmt, sizeof(fmt2));
+
+ do_log(level, forced, suffix, fmt2, args);
+}
+
+void
+sshlogdirect(LogLevel level, int forced, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ do_log(level, forced, NULL, fmt, args);
+ va_end(args);
+}
diff --git a/log.h b/log.h
index 78cda287d..6218b4177 100644
--- a/log.h
+++ b/log.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.h,v 1.24 2019/09/06 04:53:27 djm Exp $ */
+/* $OpenBSD: log.h,v 1.33 2021/04/15 16:24:31 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -16,6 +16,7 @@
#define SSH_LOG_H
#include <stdarg.h> /* va_list */
+#include "ssherr.h" /* ssh_err() */
/* Supported syslog facilities and levels. */
typedef enum {
@@ -48,36 +49,84 @@ typedef enum {
SYSLOG_LEVEL_NOT_SET = -1
} LogLevel;
-typedef void (log_handler_fn)(LogLevel, const char *, void *);
+typedef void (log_handler_fn)(LogLevel, int, const char *, void *);
-void log_init(char *, LogLevel, SyslogFacility, int);
+void log_init(const char *, LogLevel, SyslogFacility, int);
LogLevel log_level_get(void);
int log_change_level(LogLevel);
int log_is_on_stderr(void);
void log_redirect_stderr_to(const char *);
+void log_verbose_add(const char *);
+void log_verbose_reset(void);
SyslogFacility log_facility_number(char *);
-const char * log_facility_name(SyslogFacility);
+const char * log_facility_name(SyslogFacility);
LogLevel log_level_number(char *);
const char * log_level_name(LogLevel);
-void fatal(const char *, ...) __attribute__((noreturn))
- __attribute__((format(printf, 1, 2)));
-void error(const char *, ...) __attribute__((format(printf, 1, 2)));
-void sigdie(const char *, ...) __attribute__((noreturn))
- __attribute__((format(printf, 1, 2)));
-void logdie(const char *, ...) __attribute__((noreturn))
- __attribute__((format(printf, 1, 2)));
-void logit(const char *, ...) __attribute__((format(printf, 1, 2)));
-void verbose(const char *, ...) __attribute__((format(printf, 1, 2)));
-void debug(const char *, ...) __attribute__((format(printf, 1, 2)));
-void debug2(const char *, ...) __attribute__((format(printf, 1, 2)));
-void debug3(const char *, ...) __attribute__((format(printf, 1, 2)));
-
-
void set_log_handler(log_handler_fn *, void *);
-void do_log2(LogLevel, const char *, ...)
- __attribute__((format(printf, 2, 3)));
-void do_log(LogLevel, const char *, va_list);
void cleanup_exit(int) __attribute__((noreturn));
+
+void sshlog(const char *, const char *, int, int,
+ LogLevel, const char *, const char *, ...)
+ __attribute__((format(printf, 7, 8)));
+void sshlogv(const char *, const char *, int, int,
+ LogLevel, const char *, const char *, va_list);
+void sshsigdie(const char *, const char *, int, int,
+ LogLevel, const char *, const char *, ...) __attribute__((noreturn))
+ __attribute__((format(printf, 7, 8)));
+void sshlogdie(const char *, const char *, int, int,
+ LogLevel, const char *, const char *, ...) __attribute__((noreturn))
+ __attribute__((format(printf, 7, 8)));
+void sshfatal(const char *, const char *, int, int,
+ LogLevel, const char *, const char *, ...) __attribute__((noreturn))
+ __attribute__((format(printf, 7, 8)));
+void sshlogdirect(LogLevel, int, const char *, ...)
+ __attribute__((format(printf, 3, 4)));
+
+#define do_log2(level, ...) sshlog(__FILE__, __func__, __LINE__, 0, level, NULL, __VA_ARGS__)
+#define debug3(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG3, NULL, __VA_ARGS__)
+#define debug2(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG2, NULL, __VA_ARGS__)
+#define debug(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG1, NULL, __VA_ARGS__)
+#define verbose(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_VERBOSE, NULL, __VA_ARGS__)
+#define logit(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_INFO, NULL, __VA_ARGS__)
+#define error(...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__)
+#define fatal(...) sshfatal(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_FATAL, NULL, __VA_ARGS__)
+#define logdie(...) sshlogdie(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__)
+#define sigdie(...) sshsigdie(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__)
+
+/* Variants that prepend the caller's function */
+#define do_log2_f(level, ...) sshlog(__FILE__, __func__, __LINE__, 1, level, NULL, __VA_ARGS__)
+#define debug3_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG3, NULL, __VA_ARGS__)
+#define debug2_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG2, NULL, __VA_ARGS__)
+#define debug_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG1, NULL, __VA_ARGS__)
+#define verbose_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_VERBOSE, NULL, __VA_ARGS__)
+#define logit_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_INFO, NULL, __VA_ARGS__)
+#define error_f(...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__)
+#define fatal_f(...) sshfatal(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_FATAL, NULL, __VA_ARGS__)
+#define logdie_f(...) sshlogdie(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__)
+#define sigdie_f(...) sshsigdie(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__)
+
+/* Variants that appends a ssh_err message */
+#define do_log2_r(r, level, ...) sshlog(__FILE__, __func__, __LINE__, 0, level, ssh_err(r), __VA_ARGS__)
+#define debug3_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG3, ssh_err(r), __VA_ARGS__)
+#define debug2_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG2, ssh_err(r), __VA_ARGS__)
+#define debug_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_DEBUG1, ssh_err(r), __VA_ARGS__)
+#define verbose_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_VERBOSE, ssh_err(r), __VA_ARGS__)
+#define logit_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_INFO, ssh_err(r), __VA_ARGS__)
+#define error_r(r, ...) sshlog(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__)
+#define fatal_r(r, ...) sshfatal(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_FATAL, ssh_err(r), __VA_ARGS__)
+#define logdie_r(r, ...) sshlogdie(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__)
+#define sigdie_r(r, ...) sshsigdie(__FILE__, __func__, __LINE__, 0, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__)
+#define do_log2_fr(r, level, ...) sshlog(__FILE__, __func__, __LINE__, 1, level, ssh_err(r), __VA_ARGS__)
+#define debug3_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG3, ssh_err(r), __VA_ARGS__)
+#define debug2_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG2, ssh_err(r), __VA_ARGS__)
+#define debug_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_DEBUG1, ssh_err(r), __VA_ARGS__)
+#define verbose_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_VERBOSE, ssh_err(r), __VA_ARGS__)
+#define logit_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_INFO, ssh_err(r), __VA_ARGS__)
+#define error_fr(r, ...) sshlog(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__)
+#define fatal_fr(r, ...) sshfatal(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_FATAL, ssh_err(r), __VA_ARGS__)
+#define logdie_fr(r, ...) sshlogdie(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__)
+#define sigdie_fr(r, ...) sshsigdie(__FILE__, __func__, __LINE__, 1, SYSLOG_LEVEL_ERROR, ssh_err(r), __VA_ARGS__)
+
#endif
diff --git a/loginrec.c b/loginrec.c
index e5289deb8..ea058fd6f 100644
--- a/loginrec.c
+++ b/loginrec.c
@@ -778,6 +778,9 @@ construct_utmpx(struct logininfo *li, struct utmpx *utx)
strncpy(utx->ut_host, li->hostname,
MIN_SIZEOF(utx->ut_host, li->hostname));
# endif
+# ifdef HAVE_SS_IN_UTMPX
+ utx->ut_ss = li->hostaddr.sa_storage;
+# endif
# ifdef HAVE_ADDR_IN_UTMPX
/* this is just a 32-bit IP address */
if (li->hostaddr.sa.sa_family == AF_INET)
diff --git a/loginrec.h b/loginrec.h
index 62cc0e78c..02bceb604 100644
--- a/loginrec.h
+++ b/loginrec.h
@@ -94,7 +94,7 @@ struct logininfo *login_alloc_entry(pid_t pid, const char *username,
void login_free_entry(struct logininfo *li);
/* fill out a pre-allocated structure with useful information */
int login_init_entry(struct logininfo *li, pid_t pid, const char *username,
- const char *hostname, const char *line);
+ const char *hostname, const char *line);
/* place the current time in a logininfo struct */
void login_set_current_time(struct logininfo *li);
diff --git a/logintest.c b/logintest.c
index 4897ae0f9..6ee1cdc23 100644
--- a/logintest.c
+++ b/logintest.c
@@ -62,21 +62,21 @@ dump_logininfo(struct logininfo *li, char *descname)
{
/* yes I know how nasty this is */
printf("struct logininfo %s = {\n\t"
- "progname\t'%s'\n\ttype\t\t%d\n\t"
- "pid\t\t%d\n\tuid\t\t%d\n\t"
- "line\t\t'%s'\n\tusername\t'%s'\n\t"
- "hostname\t'%s'\n\texit\t\t%d\n\ttermination\t%d\n\t"
- "tv_sec\t%d\n\ttv_usec\t%d\n\t"
- "struct login_netinfo hostaddr {\n\t\t"
- "struct sockaddr sa {\n"
- "\t\t\tfamily\t%d\n\t\t}\n"
- "\t}\n"
- "}\n",
- descname, li->progname, li->type,
- li->pid, li->uid, li->line,
- li->username, li->hostname, li->exit,
- li->termination, li->tv_sec, li->tv_usec,
- li->hostaddr.sa.sa_family);
+ "progname\t'%s'\n\ttype\t\t%d\n\t"
+ "pid\t\t%d\n\tuid\t\t%d\n\t"
+ "line\t\t'%s'\n\tusername\t'%s'\n\t"
+ "hostname\t'%s'\n\texit\t\t%d\n\ttermination\t%d\n\t"
+ "tv_sec\t%d\n\ttv_usec\t%d\n\t"
+ "struct login_netinfo hostaddr {\n\t\t"
+ "struct sockaddr sa {\n"
+ "\t\t\tfamily\t%d\n\t\t}\n"
+ "\t}\n"
+ "}\n",
+ descname, li->progname, li->type,
+ li->pid, li->uid, li->line,
+ li->username, li->hostname, li->exit,
+ li->termination, li->tv_sec, li->tv_usec,
+ li->hostaddr.sa.sa_family);
}
@@ -118,7 +118,7 @@ testAPI()
/* NOTE: this is messy, but typically a program wouldn't have to set
* any of this, a sockaddr_in* would be already prepared */
memcpy((void *)&(sa_in4.sin_addr), (void *)&(he->h_addr_list[0][0]),
- sizeof(struct in_addr));
+ sizeof(struct in_addr));
login_set_addr(li1, (struct sockaddr *) &sa_in4, sizeof(sa_in4));
strlcpy(li1->hostname, "localhost", sizeof(li1->hostname));
}
@@ -145,8 +145,8 @@ testAPI()
t1 = login_get_lastlog_time(getuid());
strlcpy(s_t1, ctime(&t1), sizeof(s_t1));
printf("Before logging in:\n\tcurrent time is %d - %s\t"
- "lastlog time is %d - %s\n",
- (int)t0, s_t0, (int)t1, s_t1);
+ "lastlog time is %d - %s\n",
+ (int)t0, s_t0, (int)t1, s_t1);
#endif
printf("Performing a login on line %s ", stripline);
@@ -172,10 +172,10 @@ testAPI()
printf("at %d - %s", (int)logouttime, s_logouttime);
#endif
printf("\nThe root login shown above should be gone.\n"
- "If the root login hasn't gone, but another user on the same\n"
- "pty has, this is OK - we're hacking it here, and there\n"
- "shouldn't be two users on one pty in reality...\n"
- "-- ('who' output follows)\n");
+ "If the root login hasn't gone, but another user on the same\n"
+ "pty has, this is OK - we're hacking it here, and there\n"
+ "shouldn't be two users on one pty in reality...\n"
+ "-- ('who' output follows)\n");
login_logout(li1);
system(cmdstring);
@@ -187,24 +187,24 @@ testAPI()
printf("After logging in, lastlog time is %d - %s\n", (int)t2, s_t2);
if (t1 == t2)
printf("The lastlog times before and after logging in are the "
- "same.\nThis indicates that lastlog is ** NOT WORKING "
- "CORRECTLY **\n");
+ "same.\nThis indicates that lastlog is ** NOT WORKING "
+ "CORRECTLY **\n");
else if (t0 != t2)
/* We can be off by a second or so, even when recording works fine.
* I'm not 100% sure why, but it's true. */
printf("** The login time and the lastlog time differ.\n"
- "** This indicates that lastlog is either recording the "
- "wrong time,\n** or retrieving the wrong entry.\n"
- "If it's off by less than %d second(s) "
- "run the test again.\n", PAUSE_BEFORE_LOGOUT);
+ "** This indicates that lastlog is either recording the "
+ "wrong time,\n** or retrieving the wrong entry.\n"
+ "If it's off by less than %d second(s) "
+ "run the test again.\n", PAUSE_BEFORE_LOGOUT);
else
printf("lastlog agrees with the login time. This is a good thing.\n");
#endif
printf("--\nThe output of 'last' shown next should have "
- "an entry for root \n on %s for the time shown above:\n--\n",
- stripline);
+ "an entry for root \n on %s for the time shown above:\n--\n",
+ stripline);
snprintf(cmdstring, sizeof(cmdstring), "last | grep '%s ' | head -3",
stripline);
system(cmdstring);
diff --git a/aclocal.m4 b/m4/openssh.m4
index 25ecc49a2..4f9c3792d 100644
--- a/aclocal.m4
+++ b/m4/openssh.m4
@@ -15,12 +15,23 @@ AC_DEFUN([OSSH_CHECK_CFLAG_COMPILE], [{
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
+ (void)argv;
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
double m = l / 0.5;
long long int n = argc * 12345LL, o = 12345LL * (long long int)argc;
printf("%d %d %d %f %f %lld %lld\n", i, j, k, l, m, n, o);
+ /*
+ * Test fallthrough behaviour. clang 10's -Wimplicit-fallthrough does
+ * not understand comments and we don't use the "fallthrough" attribute
+ * that it's looking for.
+ */
+ switch(i){
+ case 0: j += i;
+ /* FALLTHROUGH */
+ default: j += k;
+ }
exit(0);
}
]])],
@@ -52,6 +63,7 @@ AC_DEFUN([OSSH_CHECK_CFLAG_LINK], [{
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
+ (void)argv;
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
@@ -90,6 +102,7 @@ AC_DEFUN([OSSH_CHECK_LDFLAG_LINK], [{
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
+ (void)argv;
/* Some math to catch -ftrapv problems in the toolchain */
int i = 123 * argc, j = 456 + argc, k = 789 - argc;
float l = i * 2.1;
@@ -118,7 +131,7 @@ dnl OSSH_CHECK_HEADER_FOR_FIELD(field, header, symbol)
dnl Does AC_EGREP_HEADER on 'header' for the string 'field'
dnl If found, set 'symbol' to be defined. Cache the result.
dnl TODO: This is not foolproof, better to compile and read from there
-AC_DEFUN(OSSH_CHECK_HEADER_FOR_FIELD, [
+AC_DEFUN([OSSH_CHECK_HEADER_FOR_FIELD], [
# look for field '$1' in header '$2'
dnl This strips characters illegal to m4 from the header filename
ossh_safe=`echo "$2" | sed 'y%./+-%__p_%'`
@@ -158,14 +171,15 @@ AC_DEFUN([TYPE_SOCKLEN_T],
curl_cv_socklen_t_equiv=
for arg2 in "struct sockaddr" void; do
for t in int size_t unsigned long "unsigned long"; do
- AC_TRY_COMPILE([
- #include <sys/types.h>
- #include <sys/socket.h>
-
- int getpeername (int, $arg2 *, $t *);
- ],[
- $t len;
- getpeername(0,0,&len);
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([[
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ int getpeername (int, $arg2 *, $t *);
+ ]], [[
+ $t len;
+ getpeername(0,0,&len);
+ ]])
],[
curl_cv_socklen_t_equiv="$t"
break
diff --git a/match.c b/match.c
index 3a8fa9d78..3ac854d38 100644
--- a/match.c
+++ b/match.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: match.c,v 1.41 2019/11/13 04:47:52 deraadt Exp $ */
+/* $OpenBSD: match.c,v 1.43 2020/11/03 22:53:12 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -53,7 +53,6 @@
* Returns true if the given string matches the pattern (which may contain ?
* and * as wildcards), and zero if it does not match.
*/
-
int
match_pattern(const char *s, const char *pattern)
{
@@ -63,8 +62,9 @@ match_pattern(const char *s, const char *pattern)
return !*s;
if (*pattern == '*') {
- /* Skip the asterisk. */
- pattern++;
+ /* Skip this and any consecutive asterisks. */
+ while (*pattern == '*')
+ pattern++;
/* If at end of pattern, accept immediately. */
if (!*pattern)
@@ -309,13 +309,13 @@ match_list(const char *client, const char *server, u_int *next)
/*
* Filter proposal using pattern-list filter.
- * "blacklist" determines sense of filter:
+ * "denylist" determines sense of filter:
* non-zero indicates that items matching filter should be excluded.
* zero indicates that only items matching filter should be included.
* returns NULL on allocation error, otherwise caller must free result.
*/
static char *
-filter_list(const char *proposal, const char *filter, int blacklist)
+filter_list(const char *proposal, const char *filter, int denylist)
{
size_t len = strlen(proposal) + 1;
char *fix_prop = malloc(len);
@@ -333,7 +333,7 @@ filter_list(const char *proposal, const char *filter, int blacklist)
*fix_prop = '\0';
while ((cp = strsep(&tmp, ",")) != NULL) {
r = match_pattern_list(cp, filter, 0);
- if ((blacklist && r != 1) || (!blacklist && r == 1)) {
+ if ((denylist && r != 1) || (!denylist && r == 1)) {
if (*fix_prop != '\0')
strlcat(fix_prop, ",", len);
strlcat(fix_prop, cp, len);
@@ -348,7 +348,7 @@ filter_list(const char *proposal, const char *filter, int blacklist)
* the 'filter' pattern list. Caller must free returned string.
*/
char *
-match_filter_blacklist(const char *proposal, const char *filter)
+match_filter_denylist(const char *proposal, const char *filter)
{
return filter_list(proposal, filter, 1);
}
@@ -358,7 +358,7 @@ match_filter_blacklist(const char *proposal, const char *filter)
* the 'filter' pattern list. Caller must free returned string.
*/
char *
-match_filter_whitelist(const char *proposal, const char *filter)
+match_filter_allowlist(const char *proposal, const char *filter)
{
return filter_list(proposal, filter, 0);
}
diff --git a/match.h b/match.h
index 3a8a6ecdc..312ca6e16 100644
--- a/match.h
+++ b/match.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: match.h,v 1.19 2019/03/06 22:14:23 dtucker Exp $ */
+/* $OpenBSD: match.h,v 1.20 2020/07/05 23:59:45 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -21,8 +21,8 @@ int match_hostname(const char *, const char *);
int match_host_and_ip(const char *, const char *, const char *);
int match_user(const char *, const char *, const char *, const char *);
char *match_list(const char *, const char *, u_int *);
-char *match_filter_blacklist(const char *, const char *);
-char *match_filter_whitelist(const char *, const char *);
+char *match_filter_denylist(const char *, const char *);
+char *match_filter_allowlist(const char *, const char *);
/* addrmatch.c */
int addr_match_list(const char *, const char *);
diff --git a/misc.c b/misc.c
index 48ff6af8b..597f9f15e 100644
--- a/misc.c
+++ b/misc.c
@@ -1,29 +1,23 @@
-/* $OpenBSD: misc.c,v 1.147 2020/04/25 06:59:36 dtucker Exp $ */
+/* $OpenBSD: misc.c,v 1.170 2021/09/26 14:01:03 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
- * Copyright (c) 2005,2006 Damien Miller. All rights reserved.
+ * Copyright (c) 2005-2020 Damien Miller. All rights reserved.
+ * Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+
#include "includes.h"
#include <sys/types.h>
@@ -62,6 +56,7 @@
#ifdef HAVE_PATHS_H
# include <paths.h>
#include <pwd.h>
+#include <grp.h>
#endif
#ifdef SSH_TUN_OPENBSD
#include <net/if.h>
@@ -91,6 +86,20 @@ chop(char *s)
}
+/* remove whitespace from end of string */
+void
+rtrim(char *s)
+{
+ size_t i;
+
+ if ((i = strlen(s)) == 0)
+ return;
+ for (i--; i > 0; i--) {
+ if (isspace((int)s[i]))
+ s[i] = '\0';
+ }
+}
+
/* set/unset filedescriptor to non-blocking */
int
set_nonblock(int fd)
@@ -237,6 +246,60 @@ set_rdomain(int fd, const char *name)
#endif
}
+int
+get_sock_af(int fd)
+{
+ struct sockaddr_storage to;
+ socklen_t tolen = sizeof(to);
+
+ memset(&to, 0, sizeof(to));
+ if (getsockname(fd, (struct sockaddr *)&to, &tolen) == -1)
+ return -1;
+#ifdef IPV4_IN_IPV6
+ if (to.ss_family == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr))
+ return AF_INET;
+#endif
+ return to.ss_family;
+}
+
+void
+set_sock_tos(int fd, int tos)
+{
+#ifndef IP_TOS_IS_BROKEN
+ int af;
+
+ switch ((af = get_sock_af(fd))) {
+ case -1:
+ /* assume not a socket */
+ break;
+ case AF_INET:
+# ifdef IP_TOS
+ debug3_f("set socket %d IP_TOS 0x%02x", fd, tos);
+ if (setsockopt(fd, IPPROTO_IP, IP_TOS,
+ &tos, sizeof(tos)) == -1) {
+ error("setsockopt socket %d IP_TOS %d: %s:",
+ fd, tos, strerror(errno));
+ }
+# endif /* IP_TOS */
+ break;
+ case AF_INET6:
+# ifdef IPV6_TCLASS
+ debug3_f("set socket %d IPV6_TCLASS 0x%02x", fd, tos);
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS,
+ &tos, sizeof(tos)) == -1) {
+ error("setsockopt socket %d IPV6_TCLASS %d: %.100s:",
+ fd, tos, strerror(errno));
+ }
+# endif /* IPV6_TCLASS */
+ break;
+ default:
+ debug2_f("unsupported socket family %d", af);
+ break;
+ }
+#endif /* IP_TOS_IS_BROKEN */
+}
+
/*
* Wait up to *timeoutp milliseconds for events on fd. Updates
* *timeoutp with time remaining.
@@ -249,17 +312,17 @@ waitfd(int fd, int *timeoutp, short events)
struct timeval t_start;
int oerrno, r;
- monotime_tv(&t_start);
pfd.fd = fd;
pfd.events = events;
for (; *timeoutp >= 0;) {
+ monotime_tv(&t_start);
r = poll(&pfd, 1, *timeoutp);
oerrno = errno;
ms_subtract_diff(&t_start, timeoutp);
errno = oerrno;
if (r > 0)
return 0;
- else if (r == -1 && errno != EAGAIN)
+ else if (r == -1 && errno != EAGAIN && errno != EINTR)
return -1;
else if (r == 0)
break;
@@ -298,12 +361,17 @@ timeout_connect(int sockfd, const struct sockaddr *serv_addr,
return connect(sockfd, serv_addr, addrlen);
set_nonblock(sockfd);
- if (connect(sockfd, serv_addr, addrlen) == 0) {
- /* Succeeded already? */
- unset_nonblock(sockfd);
- return 0;
- } else if (errno != EINPROGRESS)
- return -1;
+ for (;;) {
+ if (connect(sockfd, serv_addr, addrlen) == 0) {
+ /* Succeeded already? */
+ unset_nonblock(sockfd);
+ return 0;
+ } else if (errno == EINTR)
+ continue;
+ else if (errno != EINPROGRESS)
+ return -1;
+ break;
+ }
if (waitfd(sockfd, timeoutp, POLLIN | POLLOUT) == -1)
return -1;
@@ -392,7 +460,7 @@ pwcopy(struct passwd *pw)
struct passwd *copy = xcalloc(1, sizeof(*copy));
copy->pw_name = xstrdup(pw->pw_name);
- copy->pw_passwd = pw->pw_passwd ? xstrdup(pw->pw_passwd) : NULL;
+ copy->pw_passwd = xstrdup(pw->pw_passwd == NULL ? "*" : pw->pw_passwd);
#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
copy->pw_gecos = xstrdup(pw->pw_gecos);
#endif
@@ -490,10 +558,10 @@ a2tun(const char *s, int *remote)
*
* Return -1 if time string is invalid.
*/
-long
+int
convtime(const char *s)
{
- long total, secs, multiplier = 1;
+ long total, secs, multiplier;
const char *p;
char *endp;
@@ -507,10 +575,11 @@ convtime(const char *s)
while (*p) {
secs = strtol(p, &endp, 10);
if (p == endp ||
- (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) ||
+ (errno == ERANGE && (secs == INT_MIN || secs == INT_MAX)) ||
secs < 0)
return -1;
+ multiplier = 1;
switch (*endp++) {
case '\0':
endp--;
@@ -537,10 +606,10 @@ convtime(const char *s)
default:
return -1;
}
- if (secs >= LONG_MAX / multiplier)
+ if (secs > INT_MAX / multiplier)
return -1;
secs *= multiplier;
- if (total >= LONG_MAX - secs)
+ if (total > INT_MAX - secs)
return -1;
total += secs;
if (total < 0)
@@ -551,6 +620,43 @@ convtime(const char *s)
return total;
}
+#define TF_BUFS 8
+#define TF_LEN 9
+
+const char *
+fmt_timeframe(time_t t)
+{
+ char *buf;
+ static char tfbuf[TF_BUFS][TF_LEN]; /* ring buffer */
+ static int idx = 0;
+ unsigned int sec, min, hrs, day;
+ unsigned long long week;
+
+ buf = tfbuf[idx++];
+ if (idx == TF_BUFS)
+ idx = 0;
+
+ week = t;
+
+ sec = week % 60;
+ week /= 60;
+ min = week % 60;
+ week /= 60;
+ hrs = week % 24;
+ week /= 24;
+ day = week % 7;
+ week /= 7;
+
+ if (week > 0)
+ snprintf(buf, TF_LEN, "%02lluw%01ud%02uh", week, day, hrs);
+ else if (day > 0)
+ snprintf(buf, TF_LEN, "%01ud%02uh%02um", day, hrs, min);
+ else
+ snprintf(buf, TF_LEN, "%02u:%02u:%02u", hrs, min, sec);
+
+ return (buf);
+}
+
/*
* Returns a standardized host+port identifier string.
* Caller must free returned string.
@@ -1010,29 +1116,37 @@ freeargs(arglist *args)
* Expands tildes in the file name. Returns data allocated by xmalloc.
* Warning: this calls getpw*.
*/
-char *
-tilde_expand_filename(const char *filename, uid_t uid)
+int
+tilde_expand(const char *filename, uid_t uid, char **retp)
{
const char *path, *sep;
char user[128], *ret;
struct passwd *pw;
u_int len, slash;
- if (*filename != '~')
- return (xstrdup(filename));
+ if (*filename != '~') {
+ *retp = xstrdup(filename);
+ return 0;
+ }
filename++;
path = strchr(filename, '/');
if (path != NULL && path > filename) { /* ~user/path */
slash = path - filename;
- if (slash > sizeof(user) - 1)
- fatal("tilde_expand_filename: ~username too long");
+ if (slash > sizeof(user) - 1) {
+ error_f("~username too long");
+ return -1;
+ }
memcpy(user, filename, slash);
user[slash] = '\0';
- if ((pw = getpwnam(user)) == NULL)
- fatal("tilde_expand_filename: No such user %s", user);
- } else if ((pw = getpwuid(uid)) == NULL) /* ~/path */
- fatal("tilde_expand_filename: No such uid %ld", (long)uid);
+ if ((pw = getpwnam(user)) == NULL) {
+ error_f("No such user %s", user);
+ return -1;
+ }
+ } else if ((pw = getpwuid(uid)) == NULL) { /* ~/path */
+ error_f("No such uid %ld", (long)uid);
+ return -1;
+ }
/* Make sure directory has a trailing '/' */
len = strlen(pw->pw_dir);
@@ -1045,85 +1159,201 @@ tilde_expand_filename(const char *filename, uid_t uid)
if (path != NULL)
filename = path + 1;
- if (xasprintf(&ret, "%s%s%s", pw->pw_dir, sep, filename) >= PATH_MAX)
- fatal("tilde_expand_filename: Path too long");
+ if (xasprintf(&ret, "%s%s%s", pw->pw_dir, sep, filename) >= PATH_MAX) {
+ error_f("Path too long");
+ return -1;
+ }
+
+ *retp = ret;
+ return 0;
+}
+
+char *
+tilde_expand_filename(const char *filename, uid_t uid)
+{
+ char *ret;
- return (ret);
+ if (tilde_expand(filename, uid, &ret) != 0)
+ cleanup_exit(255);
+ return ret;
}
/*
- * Expand a string with a set of %[char] escapes. A number of escapes may be
- * specified as (char *escape_chars, char *replacement) pairs. The list must
- * be terminated by a NULL escape_char. Returns replaced string in memory
- * allocated by xmalloc.
+ * Expand a string with a set of %[char] escapes and/or ${ENVIRONMENT}
+ * substitutions. A number of escapes may be specified as
+ * (char *escape_chars, char *replacement) pairs. The list must be terminated
+ * by a NULL escape_char. Returns replaced string in memory allocated by
+ * xmalloc which the caller must free.
*/
-char *
-percent_expand(const char *string, ...)
+static char *
+vdollar_percent_expand(int *parseerror, int dollar, int percent,
+ const char *string, va_list ap)
{
#define EXPAND_MAX_KEYS 16
- u_int num_keys, i;
+ u_int num_keys = 0, i;
struct {
const char *key;
const char *repl;
} keys[EXPAND_MAX_KEYS];
struct sshbuf *buf;
- va_list ap;
- int r;
- char *ret;
+ int r, missingvar = 0;
+ char *ret = NULL, *var, *varend, *val;
+ size_t len;
if ((buf = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
-
- /* Gather keys */
- va_start(ap, string);
- for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) {
- keys[num_keys].key = va_arg(ap, char *);
- if (keys[num_keys].key == NULL)
- break;
- keys[num_keys].repl = va_arg(ap, char *);
- if (keys[num_keys].repl == NULL)
- fatal("%s: NULL replacement", __func__);
+ fatal_f("sshbuf_new failed");
+ if (parseerror == NULL)
+ fatal_f("null parseerror arg");
+ *parseerror = 1;
+
+ /* Gather keys if we're doing percent expansion. */
+ if (percent) {
+ for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) {
+ keys[num_keys].key = va_arg(ap, char *);
+ if (keys[num_keys].key == NULL)
+ break;
+ keys[num_keys].repl = va_arg(ap, char *);
+ if (keys[num_keys].repl == NULL) {
+ fatal_f("NULL replacement for token %s",
+ keys[num_keys].key);
+ }
+ }
+ if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL)
+ fatal_f("too many keys");
+ if (num_keys == 0)
+ fatal_f("percent expansion without token list");
}
- if (num_keys == EXPAND_MAX_KEYS && va_arg(ap, char *) != NULL)
- fatal("%s: too many keys", __func__);
- va_end(ap);
/* Expand string */
for (i = 0; *string != '\0'; string++) {
- if (*string != '%') {
- append:
- if ((r = sshbuf_put_u8(buf, *string)) != 0) {
- fatal("%s: sshbuf_put_u8: %s",
- __func__, ssh_err(r));
+ /* Optionally process ${ENVIRONMENT} expansions. */
+ if (dollar && string[0] == '$' && string[1] == '{') {
+ string += 2; /* skip over '${' */
+ if ((varend = strchr(string, '}')) == NULL) {
+ error_f("environment variable '%s' missing "
+ "closing '}'", string);
+ goto out;
}
+ len = varend - string;
+ if (len == 0) {
+ error_f("zero-length environment variable");
+ goto out;
+ }
+ var = xmalloc(len + 1);
+ (void)strlcpy(var, string, len + 1);
+ if ((val = getenv(var)) == NULL) {
+ error_f("env var ${%s} has no value", var);
+ missingvar = 1;
+ } else {
+ debug3_f("expand ${%s} -> '%s'", var, val);
+ if ((r = sshbuf_put(buf, val, strlen(val))) !=0)
+ fatal_fr(r, "sshbuf_put ${}");
+ }
+ free(var);
+ string += len;
+ continue;
+ }
+
+ /*
+ * Process percent expansions if we have a list of TOKENs.
+ * If we're not doing percent expansion everything just gets
+ * appended here.
+ */
+ if (*string != '%' || !percent) {
+ append:
+ if ((r = sshbuf_put_u8(buf, *string)) != 0)
+ fatal_fr(r, "sshbuf_put_u8 %%");
continue;
}
string++;
/* %% case */
if (*string == '%')
goto append;
- if (*string == '\0')
- fatal("%s: invalid format", __func__);
+ if (*string == '\0') {
+ error_f("invalid format");
+ goto out;
+ }
for (i = 0; i < num_keys; i++) {
if (strchr(keys[i].key, *string) != NULL) {
if ((r = sshbuf_put(buf, keys[i].repl,
- strlen(keys[i].repl))) != 0) {
- fatal("%s: sshbuf_put: %s",
- __func__, ssh_err(r));
- }
+ strlen(keys[i].repl))) != 0)
+ fatal_fr(r, "sshbuf_put %%-repl");
break;
}
}
- if (i >= num_keys)
- fatal("%s: unknown key %%%c", __func__, *string);
+ if (i >= num_keys) {
+ error_f("unknown key %%%c", *string);
+ goto out;
+ }
}
- if ((ret = sshbuf_dup_string(buf)) == NULL)
- fatal("%s: sshbuf_dup_string failed", __func__);
+ if (!missingvar && (ret = sshbuf_dup_string(buf)) == NULL)
+ fatal_f("sshbuf_dup_string failed");
+ *parseerror = 0;
+ out:
sshbuf_free(buf);
- return ret;
+ return *parseerror ? NULL : ret;
#undef EXPAND_MAX_KEYS
}
+/*
+ * Expand only environment variables.
+ * Note that although this function is variadic like the other similar
+ * functions, any such arguments will be unused.
+ */
+
+char *
+dollar_expand(int *parseerr, const char *string, ...)
+{
+ char *ret;
+ int err;
+ va_list ap;
+
+ va_start(ap, string);
+ ret = vdollar_percent_expand(&err, 1, 0, string, ap);
+ va_end(ap);
+ if (parseerr != NULL)
+ *parseerr = err;
+ return ret;
+}
+
+/*
+ * Returns expanded string or NULL if a specified environment variable is
+ * not defined, or calls fatal if the string is invalid.
+ */
+char *
+percent_expand(const char *string, ...)
+{
+ char *ret;
+ int err;
+ va_list ap;
+
+ va_start(ap, string);
+ ret = vdollar_percent_expand(&err, 0, 1, string, ap);
+ va_end(ap);
+ if (err)
+ fatal_f("failed");
+ return ret;
+}
+
+/*
+ * Returns expanded string or NULL if a specified environment variable is
+ * not defined, or calls fatal if the string is invalid.
+ */
+char *
+percent_dollar_expand(const char *string, ...)
+{
+ char *ret;
+ int err;
+ va_list ap;
+
+ va_start(ap, string);
+ ret = vdollar_percent_expand(&err, 1, 1, string, ap);
+ va_end(ap);
+ if (err)
+ fatal_f("failed");
+ return ret;
+}
+
int
tun_open(int tun, int mode, char **ifname)
{
@@ -1153,16 +1383,16 @@ tun_open(int tun, int mode, char **ifname)
break;
}
} else {
- debug("%s: invalid tunnel %u", __func__, tun);
+ debug_f("invalid tunnel %u", tun);
return -1;
}
if (fd == -1) {
- debug("%s: %s open: %s", __func__, name, strerror(errno));
+ debug_f("%s open: %s", name, strerror(errno));
return -1;
}
- debug("%s: %s mode %d fd %d", __func__, name, mode, fd);
+ debug_f("%s mode %d fd %d", name, mode, fd);
/* Bring interface up if it is not already */
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", tunbase, tun);
@@ -1170,16 +1400,16 @@ tun_open(int tun, int mode, char **ifname)
goto failed;
if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
- debug("%s: get interface %s flags: %s", __func__,
- ifr.ifr_name, strerror(errno));
+ debug_f("get interface %s flags: %s", ifr.ifr_name,
+ strerror(errno));
goto failed;
}
if (!(ifr.ifr_flags & IFF_UP)) {
ifr.ifr_flags |= IFF_UP;
if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
- debug("%s: activate interface %s: %s", __func__,
- ifr.ifr_name, strerror(errno));
+ debug_f("activate interface %s: %s", ifr.ifr_name,
+ strerror(errno));
goto failed;
}
}
@@ -1530,7 +1760,7 @@ mktemp_proto(char *s, size_t len)
}
r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX");
if (r < 0 || (size_t)r >= len)
- fatal("%s: template string too short", __func__);
+ fatal_f("template string too short");
}
static const struct {
@@ -1617,8 +1847,7 @@ unix_listener(const char *path, int backlog, int unlink_first)
sunaddr.sun_family = AF_UNIX;
if (strlcpy(sunaddr.sun_path, path,
sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) {
- error("%s: path \"%s\" too long for Unix domain socket",
- __func__, path);
+ error_f("path \"%s\" too long for Unix domain socket", path);
errno = ENAMETOOLONG;
return -1;
}
@@ -1626,7 +1855,7 @@ unix_listener(const char *path, int backlog, int unlink_first)
sock = socket(PF_UNIX, SOCK_STREAM, 0);
if (sock == -1) {
saved_errno = errno;
- error("%s: socket: %.100s", __func__, strerror(errno));
+ error_f("socket: %.100s", strerror(errno));
errno = saved_errno;
return -1;
}
@@ -1636,16 +1865,14 @@ unix_listener(const char *path, int backlog, int unlink_first)
}
if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) {
saved_errno = errno;
- error("%s: cannot bind to path %s: %s",
- __func__, path, strerror(errno));
+ error_f("cannot bind to path %s: %s", path, strerror(errno));
close(sock);
errno = saved_errno;
return -1;
}
if (listen(sock, backlog) == -1) {
saved_errno = errno;
- error("%s: cannot listen on path %s: %s",
- __func__, path, strerror(errno));
+ error_f("cannot listen on path %s: %s", path, strerror(errno));
close(sock);
unlink(path);
errno = saved_errno;
@@ -1721,14 +1948,13 @@ daemonized(void)
return 1;
}
-
/*
* Splits 's' into an argument vector. Handles quoted string and basic
* escape characters (\\, \", \'). Caller must free the argument vector
* and its members.
*/
int
-argv_split(const char *s, int *argcp, char ***argvp)
+argv_split(const char *s, int *argcp, char ***argvp, int terminate_on_comment)
{
int r = SSH_ERR_INTERNAL_ERROR;
int argc = 0, quote, i, j;
@@ -1741,14 +1967,10 @@ argv_split(const char *s, int *argcp, char ***argvp)
/* Skip leading whitespace */
if (s[i] == ' ' || s[i] == '\t')
continue;
-
+ if (terminate_on_comment && s[i] == '#')
+ break;
/* Start of a token */
quote = 0;
- if (s[i] == '\\' &&
- (s[i + 1] == '\'' || s[i + 1] == '\"' || s[i + 1] == '\\'))
- i++;
- else if (s[i] == '\'' || s[i] == '"')
- quote = s[i++];
argv = xreallocarray(argv, (argc + 2), sizeof(*argv));
arg = argv[argc++] = xcalloc(1, strlen(s + i) + 1);
@@ -1759,7 +1981,8 @@ argv_split(const char *s, int *argcp, char ***argvp)
if (s[i] == '\\') {
if (s[i + 1] == '\'' ||
s[i + 1] == '\"' ||
- s[i + 1] == '\\') {
+ s[i + 1] == '\\' ||
+ (quote == 0 && s[i + 1] == ' ')) {
i++; /* Skip '\' */
arg[j++] = s[i];
} else {
@@ -1768,8 +1991,10 @@ argv_split(const char *s, int *argcp, char ***argvp)
}
} else if (quote == 0 && (s[i] == ' ' || s[i] == '\t'))
break; /* done */
+ else if (quote == 0 && (s[i] == '\"' || s[i] == '\''))
+ quote = s[i]; /* quote start */
else if (quote != 0 && s[i] == quote)
- break; /* done */
+ quote = 0; /* quote end */
else
arg[j++] = s[i];
}
@@ -1809,7 +2034,7 @@ argv_assemble(int argc, char **argv)
struct sshbuf *buf, *arg;
if ((buf = sshbuf_new()) == NULL || (arg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
for (i = 0; i < argc; i++) {
ws = 0;
@@ -1834,17 +2059,16 @@ argv_assemble(int argc, char **argv)
break;
}
if (r != 0)
- fatal("%s: sshbuf_put_u8: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_put_u8");
}
if ((i != 0 && (r = sshbuf_put_u8(buf, ' ')) != 0) ||
(ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0) ||
(r = sshbuf_putb(buf, arg)) != 0 ||
(ws != 0 && (r = sshbuf_put_u8(buf, '"')) != 0))
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
}
if ((ret = malloc(sshbuf_len(buf) + 1)) == NULL)
- fatal("%s: malloc failed", __func__);
+ fatal_f("malloc failed");
memcpy(ret, sshbuf_ptr(buf), sshbuf_len(buf));
ret[sshbuf_len(buf)] = '\0';
sshbuf_free(buf);
@@ -1852,6 +2076,36 @@ argv_assemble(int argc, char **argv)
return ret;
}
+char *
+argv_next(int *argcp, char ***argvp)
+{
+ char *ret = (*argvp)[0];
+
+ if (*argcp > 0 && ret != NULL) {
+ (*argcp)--;
+ (*argvp)++;
+ }
+ return ret;
+}
+
+void
+argv_consume(int *argcp)
+{
+ *argcp = 0;
+}
+
+void
+argv_free(char **av, int ac)
+{
+ int i;
+
+ if (av == NULL)
+ return;
+ for (i = 0; i < ac; i++)
+ free(av[i]);
+ free(av);
+}
+
/* Returns 0 if pid exited cleanly, non-zero otherwise */
int
exited_cleanly(pid_t pid, const char *tag, const char *cmd, int quiet)
@@ -1860,7 +2114,7 @@ exited_cleanly(pid_t pid, const char *tag, const char *cmd, int quiet)
while (waitpid(pid, &status, 0) == -1) {
if (errno != EINTR) {
- error("%s: waitpid: %s", tag, strerror(errno));
+ error("%s waitpid: %s", tag, strerror(errno));
return -1;
}
}
@@ -2156,10 +2410,13 @@ parse_absolute_time(const char *s, uint64_t *tp)
return 0;
}
+/* On OpenBSD time_t is int64_t which is long long. */
+/* #define SSH_TIME_T_MAX LLONG_MAX */
+
void
format_absolute_time(uint64_t t, char *buf, size_t len)
{
- time_t tt = t > INT_MAX ? INT_MAX : t; /* XXX revisit in 2038 :P */
+ time_t tt = t > SSH_TIME_T_MAX ? SSH_TIME_T_MAX : t;
struct tm tm;
localtime_r(&tt, &tm);
@@ -2254,6 +2511,32 @@ opt_match(const char **opts, const char *term)
return 0;
}
+void
+opt_array_append2(const char *file, const int line, const char *directive,
+ char ***array, int **iarray, u_int *lp, const char *s, int i)
+{
+
+ if (*lp >= INT_MAX)
+ fatal("%s line %d: Too many %s entries", file, line, directive);
+
+ if (iarray != NULL) {
+ *iarray = xrecallocarray(*iarray, *lp, *lp + 1,
+ sizeof(**iarray));
+ (*iarray)[*lp] = i;
+ }
+
+ *array = xrecallocarray(*array, *lp, *lp + 1, sizeof(**array));
+ (*array)[*lp] = xstrdup(s);
+ (*lp)++;
+}
+
+void
+opt_array_append(const char *file, const int line, const char *directive,
+ char ***array, u_int *lp, const char *s)
+{
+ opt_array_append2(file, line, directive, array, NULL, lp, s, 0);
+}
+
sshsig_t
ssh_signal(int signum, sshsig_t handler)
{
@@ -2273,3 +2556,214 @@ ssh_signal(int signum, sshsig_t handler)
}
return osa.sa_handler;
}
+
+int
+stdfd_devnull(int do_stdin, int do_stdout, int do_stderr)
+{
+ int devnull, ret = 0;
+
+ if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
+ error_f("open %s: %s", _PATH_DEVNULL,
+ strerror(errno));
+ return -1;
+ }
+ if ((do_stdin && dup2(devnull, STDIN_FILENO) == -1) ||
+ (do_stdout && dup2(devnull, STDOUT_FILENO) == -1) ||
+ (do_stderr && dup2(devnull, STDERR_FILENO) == -1)) {
+ error_f("dup2: %s", strerror(errno));
+ ret = -1;
+ }
+ if (devnull > STDERR_FILENO)
+ close(devnull);
+ return ret;
+}
+
+/*
+ * Runs command in a subprocess with a minimal environment.
+ * Returns pid on success, 0 on failure.
+ * The child stdout and stderr maybe captured, left attached or sent to
+ * /dev/null depending on the contents of flags.
+ * "tag" is prepended to log messages.
+ * NB. "command" is only used for logging; the actual command executed is
+ * av[0].
+ */
+pid_t
+subprocess(const char *tag, const char *command,
+ int ac, char **av, FILE **child, u_int flags,
+ struct passwd *pw, privdrop_fn *drop_privs, privrestore_fn *restore_privs)
+{
+ FILE *f = NULL;
+ struct stat st;
+ int fd, devnull, p[2], i;
+ pid_t pid;
+ char *cp, errmsg[512];
+ u_int nenv = 0;
+ char **env = NULL;
+
+ /* If dropping privs, then must specify user and restore function */
+ if (drop_privs != NULL && (pw == NULL || restore_privs == NULL)) {
+ error("%s: inconsistent arguments", tag); /* XXX fatal? */
+ return 0;
+ }
+ if (pw == NULL && (pw = getpwuid(getuid())) == NULL) {
+ error("%s: no user for current uid", tag);
+ return 0;
+ }
+ if (child != NULL)
+ *child = NULL;
+
+ debug3_f("%s command \"%s\" running as %s (flags 0x%x)",
+ tag, command, pw->pw_name, flags);
+
+ /* Check consistency */
+ if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 &&
+ (flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0) {
+ error_f("inconsistent flags");
+ return 0;
+ }
+ if (((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0) != (child == NULL)) {
+ error_f("inconsistent flags/output");
+ return 0;
+ }
+
+ /*
+ * If executing an explicit binary, then verify the it exists
+ * and appears safe-ish to execute
+ */
+ if (!path_absolute(av[0])) {
+ error("%s path is not absolute", tag);
+ return 0;
+ }
+ if (drop_privs != NULL)
+ drop_privs(pw);
+ if (stat(av[0], &st) == -1) {
+ error("Could not stat %s \"%s\": %s", tag,
+ av[0], strerror(errno));
+ goto restore_return;
+ }
+ if ((flags & SSH_SUBPROCESS_UNSAFE_PATH) == 0 &&
+ safe_path(av[0], &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) {
+ error("Unsafe %s \"%s\": %s", tag, av[0], errmsg);
+ goto restore_return;
+ }
+ /* Prepare to keep the child's stdout if requested */
+ if (pipe(p) == -1) {
+ error("%s: pipe: %s", tag, strerror(errno));
+ restore_return:
+ if (restore_privs != NULL)
+ restore_privs();
+ return 0;
+ }
+ if (restore_privs != NULL)
+ restore_privs();
+
+ switch ((pid = fork())) {
+ case -1: /* error */
+ error("%s: fork: %s", tag, strerror(errno));
+ close(p[0]);
+ close(p[1]);
+ return 0;
+ case 0: /* child */
+ /* Prepare a minimal environment for the child. */
+ if ((flags & SSH_SUBPROCESS_PRESERVE_ENV) == 0) {
+ nenv = 5;
+ env = xcalloc(sizeof(*env), nenv);
+ child_set_env(&env, &nenv, "PATH", _PATH_STDPATH);
+ child_set_env(&env, &nenv, "USER", pw->pw_name);
+ child_set_env(&env, &nenv, "LOGNAME", pw->pw_name);
+ child_set_env(&env, &nenv, "HOME", pw->pw_dir);
+ if ((cp = getenv("LANG")) != NULL)
+ child_set_env(&env, &nenv, "LANG", cp);
+ }
+
+ for (i = 1; i < NSIG; i++)
+ ssh_signal(i, SIG_DFL);
+
+ if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
+ error("%s: open %s: %s", tag, _PATH_DEVNULL,
+ strerror(errno));
+ _exit(1);
+ }
+ if (dup2(devnull, STDIN_FILENO) == -1) {
+ error("%s: dup2: %s", tag, strerror(errno));
+ _exit(1);
+ }
+
+ /* Set up stdout as requested; leave stderr in place for now. */
+ fd = -1;
+ if ((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) != 0)
+ fd = p[1];
+ else if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0)
+ fd = devnull;
+ if (fd != -1 && dup2(fd, STDOUT_FILENO) == -1) {
+ error("%s: dup2: %s", tag, strerror(errno));
+ _exit(1);
+ }
+ closefrom(STDERR_FILENO + 1);
+
+ if (geteuid() == 0 &&
+ initgroups(pw->pw_name, pw->pw_gid) == -1) {
+ error("%s: initgroups(%s, %u): %s", tag,
+ pw->pw_name, (u_int)pw->pw_gid, strerror(errno));
+ _exit(1);
+ }
+ if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1) {
+ error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid,
+ strerror(errno));
+ _exit(1);
+ }
+ if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) {
+ error("%s: setresuid %u: %s", tag, (u_int)pw->pw_uid,
+ strerror(errno));
+ _exit(1);
+ }
+ /* stdin is pointed to /dev/null at this point */
+ if ((flags & SSH_SUBPROCESS_STDOUT_DISCARD) != 0 &&
+ dup2(STDIN_FILENO, STDERR_FILENO) == -1) {
+ error("%s: dup2: %s", tag, strerror(errno));
+ _exit(1);
+ }
+ if (env != NULL)
+ execve(av[0], av, env);
+ else
+ execv(av[0], av);
+ error("%s %s \"%s\": %s", tag, env == NULL ? "execv" : "execve",
+ command, strerror(errno));
+ _exit(127);
+ default: /* parent */
+ break;
+ }
+
+ close(p[1]);
+ if ((flags & SSH_SUBPROCESS_STDOUT_CAPTURE) == 0)
+ close(p[0]);
+ else if ((f = fdopen(p[0], "r")) == NULL) {
+ error("%s: fdopen: %s", tag, strerror(errno));
+ close(p[0]);
+ /* Don't leave zombie child */
+ kill(pid, SIGTERM);
+ while (waitpid(pid, NULL, 0) == -1 && errno == EINTR)
+ ;
+ return 0;
+ }
+ /* Success */
+ debug3_f("%s pid %ld", tag, (long)pid);
+ if (child != NULL)
+ *child = f;
+ return pid;
+}
+
+const char *
+lookup_env_in_list(const char *env, char * const *envs, size_t nenvs)
+{
+ size_t i, envlen;
+
+ envlen = strlen(env);
+ for (i = 0; i < nenvs; i++) {
+ if (strncmp(envs[i], env, envlen) == 0 &&
+ envs[i][envlen] == '=') {
+ return envs[i] + envlen + 1;
+ }
+ }
+ return NULL;
+}
diff --git a/misc.h b/misc.h
index 4a05db2da..2e2dca54b 100644
--- a/misc.h
+++ b/misc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.h,v 1.84 2020/01/24 23:54:40 djm Exp $ */
+/* $OpenBSD: misc.h,v 1.98 2021/08/09 23:47:44 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -18,6 +18,7 @@
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <stdio.h>
/* Data structure for representing a forwarding request. */
struct Forward {
@@ -44,6 +45,7 @@ struct ForwardOptions {
/* misc.c */
char *chop(char *);
+void rtrim(char *);
void skip_space(char **);
char *strdelim(char **);
char *strdelimw(char **);
@@ -53,6 +55,8 @@ void set_nodelay(int);
int set_reuseaddr(int);
char *get_rdomain(int);
int set_rdomain(int, const char *);
+int get_sock_af(int);
+void set_sock_tos(int, int);
int waitrfd(int, int *);
int timeout_connect(int, const struct sockaddr *, socklen_t, int *);
int a2port(const char *);
@@ -65,9 +69,14 @@ char *colon(char *);
int parse_user_host_path(const char *, char **, char **, char **);
int parse_user_host_port(const char *, char **, char **, int *);
int parse_uri(const char *, const char *, char **, char **, int *, char **);
-long convtime(const char *);
+int convtime(const char *);
+const char *fmt_timeframe(time_t t);
+int tilde_expand(const char *, uid_t, char **);
char *tilde_expand_filename(const char *, uid_t);
+
+char *dollar_expand(int *, const char *string, ...);
char *percent_expand(const char *, ...) __attribute__((__sentinel__));
+char *percent_dollar_expand(const char *, ...) __attribute__((__sentinel__));
char *tohex(const void *, size_t);
void xextendf(char **s, const char *sep, const char *fmt, ...)
__attribute__((__format__ (printf, 3, 4))) __attribute__((__nonnull__ (3)));
@@ -86,12 +95,23 @@ const char *atoi_err(const char *, int *);
int parse_absolute_time(const char *, uint64_t *);
void format_absolute_time(uint64_t, char *, size_t);
int path_absolute(const char *);
+int stdfd_devnull(int, int, int);
void sock_set_v6only(int);
struct passwd *pwcopy(struct passwd *);
const char *ssh_gai_strerror(int);
+typedef void privdrop_fn(struct passwd *);
+typedef void privrestore_fn(void);
+#define SSH_SUBPROCESS_STDOUT_DISCARD (1) /* Discard stdout */
+#define SSH_SUBPROCESS_STDOUT_CAPTURE (1<<1) /* Redirect stdout */
+#define SSH_SUBPROCESS_STDERR_DISCARD (1<<2) /* Discard stderr */
+#define SSH_SUBPROCESS_UNSAFE_PATH (1<<3) /* Don't check for safe cmd */
+#define SSH_SUBPROCESS_PRESERVE_ENV (1<<4) /* Keep parent environment */
+pid_t subprocess(const char *, const char *, int, char **, FILE **, u_int,
+ struct passwd *, privdrop_fn *, privrestore_fn *);
+
typedef struct arglist arglist;
struct arglist {
char **list;
@@ -99,9 +119,9 @@ struct arglist {
u_int nalloc;
};
void addargs(arglist *, char *, ...)
- __attribute__((format(printf, 2, 3)));
+ __attribute__((format(printf, 2, 3)));
void replacearg(arglist *, u_int, char *, ...)
- __attribute__((format(printf, 3, 4)));
+ __attribute__((format(printf, 3, 4)));
void freeargs(arglist *);
int tun_open(int, int, char **);
@@ -156,23 +176,36 @@ const char *iptos2str(int);
void mktemp_proto(char *, size_t);
void child_set_env(char ***envp, u_int *envsizep, const char *name,
- const char *value);
+ const char *value);
+const char *lookup_env_in_list(const char *env,
+ char * const *envs, size_t nenvs);
-int argv_split(const char *, int *, char ***);
+int argv_split(const char *, int *, char ***, int);
char *argv_assemble(int, char **argv);
+char *argv_next(int *, char ***);
+void argv_consume(int *);
+void argv_free(char **, int);
+
int exited_cleanly(pid_t, const char *, const char *, int);
struct stat;
int safe_path(const char *, struct stat *, const char *, uid_t,
- char *, size_t);
+ char *, size_t);
int safe_path_fd(int, const char *, struct passwd *,
- char *err, size_t errlen);
+ char *err, size_t errlen);
/* authorized_key-style options parsing helpers */
int opt_flag(const char *opt, int allow_negate, const char **optsp);
char *opt_dequote(const char **sp, const char **errstrp);
int opt_match(const char **opts, const char *term);
+/* readconf/servconf option lists */
+void opt_array_append(const char *file, const int line,
+ const char *directive, char ***array, u_int *lp, const char *s);
+void opt_array_append2(const char *file, const int line,
+ const char *directive, char ***array, int **iarray, u_int *lp,
+ const char *s, int i);
+
/* readpass.c */
#define RP_ECHO 0x0001
@@ -186,7 +219,8 @@ char *read_passphrase(const char *, int);
int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2)));
struct notifier_ctx *notify_start(int, const char *, ...)
__attribute__((format(printf, 2, 3)));
-void notify_complete(struct notifier_ctx *);
+void notify_complete(struct notifier_ctx *, const char *, ...)
+ __attribute__((format(printf, 2, 3)));
#define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
#define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b))
@@ -194,4 +228,5 @@ void notify_complete(struct notifier_ctx *);
typedef void (*sshsig_t)(int);
sshsig_t ssh_signal(int, sshsig_t);
+
#endif /* _MISC_H */
diff --git a/moduli b/moduli
index 10e85440f..81afe331b 100644
--- a/moduli
+++ b/moduli
@@ -1,415 +1,450 @@
-# $OpenBSD: moduli,v 1.26 2020/02/20 05:41:50 dtucker Exp $
+# $OpenBSD: moduli,v 1.30 2021/05/17 07:22:45 dtucker Exp $
# Time Type Tests Tries Size Generator Modulus
-20191022074127 2 6 100 2047 5 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C0FFE0C2D7
-20191022074138 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C0FFEE1D33
-20191022074152 2 6 100 2047 5 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C1000302CF
-20191022074200 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C10009CAA3
-20191022074209 2 6 100 2047 5 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C1000E102F
-20191022074218 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C10017AEC3
-20191022074224 2 6 100 2047 5 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C1001AC4BF
-20191022074243 2 6 100 2047 5 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C10036E7A7
-20191022074322 2 6 100 2047 5 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C100727D9F
-20191022074342 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C10091E09B
-20191022074428 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C100DB96B3
-20191022074435 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C100E315C3
-20191022074440 2 6 100 2047 5 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C100E4BB67
-20191022074450 2 6 100 2047 5 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C100EFF477
-20191022074526 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C10125A5DB
-20191022074629 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C1019192BB
-20191022074654 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C101BD818B
-20191022074721 2 6 100 2047 5 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C101E63DAF
-20191022074911 2 6 100 2047 5 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C102A7DFE7
-20191022074915 2 6 100 2047 5 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C102A7EDF7
-20191022074926 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C102B62DA3
-20191022075007 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C102F7B693
-20191022075045 2 6 100 2047 5 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C1033B1D1F
-20191022075211 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C103CDEA43
-20191022075252 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C10417630B
-20191022075337 2 6 100 2047 5 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C10462BA5F
-20191022075408 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C104906FA3
-20191022075418 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C1049C8563
-20191022075526 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C10516447B
-20191022075538 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C105263DC3
-20191022075545 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C1052B9CB3
-20191022075648 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C105985083
-20191022075711 2 6 100 2047 5 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C105B6F457
-20191022075721 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C105C3BB0B
-20191022075832 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C1064323B3
-20191022075846 2 6 100 2047 5 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C106578B1F
-20191022075941 2 6 100 2047 5 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C106B58ADF
-20191022075955 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C106CA5743
-20191022080041 2 6 100 2047 5 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C10715FF37
-20191022080105 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C1073A7C3B
-20191022080147 2 6 100 2047 5 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C10782FEF7
-20191022080206 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C1079A53A3
-20191022080212 2 6 100 2047 2 E854C2A5759DFE93314B4F76AA4E7A249192AD0B0C70B1E62F3E0B4A37D181C7D1A233312886ED675788CBBC2B384D16C0CA8E5DED996C54F68568F21D6A2333E189848A5271AC0CA6F3DAAAE469F98E1B5223CB4253653FA82242C4D29AD65E878EA91522C51CF98774952FDD9453406B4AB50A7CDFA97BB4650F601DEC496C5839F98CD774BC0F9B57581633771865F175F3D72EFAB15D377CAB2EFBD812D6F13FAD3181323BDBD95BF44703FF38225883FDF4A536DA17F8C3441459AF90528DDA015E85A978C0ABB4708407B9394C8DFB4B654348131E7EA91FCF853C44D055ADEEAE40486AF9E1724D55CA27F97F7563A82EA86B661ED02383C1079CA49B
-20191022080437 2 6 100 2047 2 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC6254F1CC3
-20191022080445 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC6255528FF
-20191022080450 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC625566D5F
-20191022080507 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC6256E3B7F
-20191022080516 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC62573826F
-20191022080529 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC6258313D7
-20191022080539 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC6258FAE9F
-20191022080552 2 6 100 2047 2 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC625A1898B
-20191022080620 2 6 100 2047 2 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC625CCD3BB
-20191022080644 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC625F373DF
-20191022080653 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC625FE7A37
-20191022080713 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC62618F277
-20191022080742 2 6 100 2047 2 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC6264B5263
-20191022080848 2 6 100 2047 2 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC626BEAA8B
-20191022080900 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC626CD618F
-20191022080911 2 6 100 2047 2 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC626D33B5B
-20191022080939 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC62703D917
-20191022081024 2 6 100 2047 2 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC6273B779B
-20191022081034 2 6 100 2047 2 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC627427EAB
-20191022081413 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC62802E907
-20191022081751 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC628B7905F
-20191022081834 2 6 100 2047 2 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC628DBDDF3
-20191022081843 2 6 100 2047 2 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC628DD29D3
-20191022081901 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC628E650F7
-20191022081950 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC6290B1487
-20191022082140 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC62959CDF7
-20191022082225 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC6297568D7
-20191022082400 2 6 100 2047 2 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC629B7AC1B
-20191022082607 2 6 100 2047 2 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC62A2EF923
-20191022082624 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC62A3A2537
-20191022082651 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC62A50145F
-20191022082739 2 6 100 2047 2 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC62A77164B
-20191022082909 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC62AD303A7
-20191022082923 2 6 100 2047 2 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC62AD5CF33
-20191022083101 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC62B343BEF
-20191022083132 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC62B47F117
-20191022083152 2 6 100 2047 2 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC62B53A7EB
-20191022083332 2 6 100 2047 5 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC62B9ED527
-20191022083541 2 6 100 2047 2 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC62BFDF373
-20191022083653 2 6 100 2047 2 C66D2C1883042B443CFE0A10A9DE4F2120CB375E93A50CEF11ADD1B8F8ED9923BBE9E231DDC9F241621E6FC0DC320B783086E419F0D746394CECDE3E7AE09E87956DB1ED4E517A9661F6361EA745ECB5841BB8B7A12AA7ECE0CB262D6462AE527E1D4562DB853E712CAAC8971C17A3D4D3A98187A3E78A0FFBF46C94A4EAA09CD4E81973862E8DE4EC5A64ED78C4524300ED4727A365FFE41F5EF11325038F788DE6ECC6B93D77B6435F333AED77FFC5EE20D166E9766BCEFF7A0399601CAD4E1D746C59A5C0775375F76F2CC92F7222854A179902F3F324AC56996CC6AAA3612051EB7AF7EFB3F199FFD5A0661B6B8ECFB8E71C256DF5275B932FC62C3DC8A3
-20191022092407 2 6 100 3071 5 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA50A338107
-20191022094427 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA50B5A745B
-20191022095026 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA50BB26CFB
-20191022095757 2 6 100 3071 5 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA50C22C577
-20191022100015 2 6 100 3071 5 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA50C3FB8DF
-20191022101519 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA50D2350DB
-20191022102519 2 6 100 3071 5 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA50DB8BE5F
-20191022103601 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA50E50FDAB
-20191022105902 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA50FDC58C3
-20191022110723 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA510777B23
-20191022111301 2 6 100 3071 5 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA510E968FF
-20191022111931 2 6 100 3071 5 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA51168241F
-20191022112616 2 6 100 3071 5 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA511E89D1F
-20191022115052 2 6 100 3071 5 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA513DB748F
-20191022121302 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA515D683FB
-20191022121526 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA5160BAA4B
-20191022121542 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA5160BED3B
-20191022121601 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA5160E3E63
-20191022121811 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA5164A2E73
-20191022122332 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA517055113
-20191022122412 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA517133383
-20191022122637 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA517638283
-20191022122836 2 6 100 3071 5 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA5179FD6A7
-20191022123100 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA517EAE913
-20191022123327 2 6 100 3071 5 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA5182B9D27
-20191022123424 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA518407A6B
-20191022123511 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA5184FB45B
-20191022123600 2 6 100 3071 5 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA51863E15F
-20191022123622 2 6 100 3071 5 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA518664AB7
-20191022124625 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA519AC1C6B
-20191022124824 2 6 100 3071 5 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA519E8D89F
-20191022125143 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA51A5644B3
-20191022125456 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA51AC223CB
-20191022130231 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA51BC05D9B
-20191022130435 2 6 100 3071 2 D00135D249B408C9C43A9853424ACA3EDF29C91A8760DB5CE2C29A213031753FCBF3A8892770E231C072CA20C6EE29FAD67E50456D8E08CEADB2741F25A802DB85BD3A1F2DDEA57736D8E19AFDE970D9C2345E6A0B734D296DA2773A565F509DF0C637A2611C59D93E22F88D1600FD6798D6251F8F6F6AD12654A7DF7DBD559F4BCF140BBCA454F23F75DDF40531DE17AE102D98E69CF4A027E5614C2ADB4E724F41EF72C6C54F5132379E53787F916D1164FF74EE411A513515F4BE5DC64712B0E786A690520BA4ACC7B4F95CDCF1D39F5D41D8725FA194AD1CDA0604F67FA4C30B342FF8334DF973090113EF54EC82BB7184356A5D076CCEE598FEEE728A9C6DAE101CF412CCCF320F430CF1754E10D24F876B11DF347DF662E58EAF1642D7D4ABDE5F097EF9C8EF567D33D11AA7F7C8DCC6E2BAA2702CF21832F33215A8B4D8CF5026FB71C4892B7D57F692EAB9463FE4BA79DCE00442BBD41F0E539BFDF58151B295B4B52C43EE071E0DB45EFBCF7C2402C2719283B2188A7BA51BFF7E23
-20191022130821 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EDF6A052B
-20191022131106 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EDFBF6B4B
-20191022131309 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EDFFDD323
-20191022131339 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE008716B
-20191022131426 2 6 100 3071 5 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE01A5ECF
-20191022131921 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE0BF992B
-20191022132230 2 6 100 3071 5 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE127F08F
-20191022132941 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE226E25B
-20191022133745 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE33AB123
-20191022134534 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE44106F3
-20191022134625 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE455482B
-20191022134720 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE46CCF9B
-20191022134822 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE489D84B
-20191022135012 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE4C1DAE3
-20191022135216 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE5043D3B
-20191022135757 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE57878BB
-20191022140734 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE6BA655B
-20191022142332 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE8EAF59B
-20191022142420 2 6 100 3071 5 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE8FD9DD7
-20191022142754 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE9733DBB
-20191022142817 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE975F4B3
-20191022142942 2 6 100 3071 5 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EE9A37157
-20191022144132 2 6 100 3071 5 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EEB21454F
-20191022144147 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EEB22B7DB
-20191022144244 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EEB38090B
-20191022144542 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EEB95B34B
-20191022145051 2 6 100 3071 5 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EEC40A7FF
-20191022145134 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EEC502BF3
-20191022145406 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EECA2580B
-20191022145505 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EECBDBF73
-20191022150136 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EED9F7463
-20191022150745 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EEE758BDB
-20191022151026 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EEECBE16B
-20191022151204 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EEEFDA69B
-20191022151244 2 6 100 3071 5 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EEF0D0497
-20191022151301 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EEF0FF43B
-20191022151431 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EEF3CEEB3
-20191022151535 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EEF5CB1A3
-20191022152032 2 6 100 3071 5 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EF00699A7
-20191022152057 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EF00EFCAB
-20191022152637 2 6 100 3071 2 DF2C9C2AE196431BA2F72808B4B3BEE51B068BC569BB83E2E500DF23BB7A3034053999EC562CC1DD8064F2F026E557D069B42670BD4AEFB0ABD18C6BEF70FA0CDC33A59CA1B4E92576A87A81140834C7F8F6BB3BD3C0B1ABBC39E3F85348B097157EAB5115CDCE8A1274D3E95A1A77A0FF34C11ECBCC54C0B95F2A37FFDD00ECD37C74137358475F72FD37B6580DB272E469D382B7A22FBE9859E8C5CC42CCFE2E2E0EF51F90697E0CE7459FE037B8870CBE7C636160F98E6B3FD98EBADC5749E1DFFE5118C757886D668C4355018A78E76593A4268D5783507A31A12625DDE4DB30DF12233756F3690681E3E91BDB2BB4D36A6B1E77F23C7EC39B57582203E4FC4AFC2AAB33D10BC4A1EE6687A6524B9A0BA6ED3347764E880FBB6B645EF091E42567813FA31A97B39F185BFB303CEC2EAE412913351C926B3F14A5EAE1CEA771F333374DA7CF83D16C3048367B05432BEDC88DF66F92D8942ACED0E83E804B8CFE8A75BD9AB504D09B286EC7FB175A2A6DA848CD7AB3503877077EF0D0F343
-20191022162825 2 6 100 4095 2 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D813960B5FB
-20191022170230 2 6 100 4095 2 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D813B823183
-20191022173749 2 6 100 4095 5 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D813DBE76FF
-20191022182715 2 6 100 4095 2 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D8140DADF3B
-20191022183421 2 6 100 4095 2 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D814147138B
-20191022184621 2 6 100 4095 2 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D8142020493
-20191022185705 2 6 100 4095 5 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D8142A5D767
-20191022190031 2 6 100 4095 5 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D8142D4B05F
-20191022190457 2 6 100 4095 5 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D81431290D7
-20191022190552 2 6 100 4095 5 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D814318C56F
-20191022191638 2 6 100 4095 2 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D8143BDC2DB
-20191022191758 2 6 100 4095 5 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D8143CAE497
-20191022192300 2 6 100 4095 5 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D8144142F3F
-20191022195622 2 6 100 4095 2 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D814632A81B
-20191022195854 2 6 100 4095 2 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D8146547CD3
-20191022200200 2 6 100 4095 5 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D81467EFE3F
-20191022205134 2 6 100 4095 2 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D81499F9BF3
-20191022211317 2 6 100 4095 5 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D814AF7C2DF
-20191022212155 2 6 100 4095 5 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D814B7B777F
-20191022213552 2 6 100 4095 5 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D814C560507
-20191022215648 2 6 100 4095 2 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D814DA0CEEB
-20191022215902 2 6 100 4095 2 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D814DBD146B
-20191022221214 2 6 100 4095 5 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D814E8802CF
-20191022222728 2 6 100 4095 2 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D814F6F35AB
-20191022224558 2 6 100 4095 2 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D8150919C63
-20191022224953 2 6 100 4095 5 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D8150C9F1CF
-20191022225735 2 6 100 4095 2 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D81513C4A13
-20191022234711 2 6 100 4095 2 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D81544BEA1B
-20191023000745 2 6 100 4095 2 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D81558FF6DB
-20191023002021 2 6 100 4095 2 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D81564FD2C3
-20191023002706 2 6 100 4095 5 CC199B2E429DD1809E193696BF0F2AB45FFC1E077B916F4E9E453876787A644C71CB859FC28B47CEA27D037E3B1F36EE8F5ACFB5D7315177F67A65CBCCB359E658120697DAFB3695C560A2693A7F1D7B22A1F8DF14987A2615D3E2E2C99232DDCF03F12248975CF039EE2DB522CEBC0391B6AA2CC7E45866DDC19D62E6A835C8347F6A447E6A6266DDFAD3197405E66C932E4A1213186F67F843E1962FD311F97062775E1FE9D0DE2525187275D01694AD66E670A40BA284BEE0FB7C64D1A79C2A18786E819FCF996631115EC212F37584F7203E6F0EE60C3963BF148A288D68B2800AF662CBBCDF8235A8DC206968ED54E3EB7C4D233C98804AE2A70DC47E995535F98C0DEBDBFDAFA8E532C6EB998925A0EEA652957973DC7643B1B5C66FF2D22C3205E96D67D1A67D2EBB9AAEC446A29EB0687550F78C18A398422EC07954B9A730FEDBAA0AD5ED90BB892C80A77AE5D27DA0DA0D3EC3075C10C86948F0B3D3DC2393673B226A3F6364DFF3D027B38BA51481461C1BF5F3C3FFBBEEADC882B5D0F4C5F59D977AB6E00A25066D8BF473481A1EA441A896D46C829DB1A489CB09FD9E1B1D09B4F1B854041583FAD18D6D303487DE1DC89D87F599920FA8EEDD4A3B64A520C3EC3AB670E93C89D0D43BC858FD991A78DDEBA72A5998DAD5AAE0123FF9E0F2E344C42E5581FFAAC36E54644B1AC1C021A7D6E9096D8156B28D27
-20191023011355 2 6 100 4095 5 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC1460883F
-20191023012442 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC1509A3E3
-20191023014214 2 6 100 4095 5 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC1620E157
-20191023015245 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC16C48533
-20191023020841 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC17C54673
-20191023021754 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC1857058B
-20191023021829 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC1857094B
-20191023022432 2 6 100 4095 5 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC18B12DFF
-20191023030433 2 6 100 4095 5 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC1B390A47
-20191023031027 2 6 100 4095 5 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC1B90EEA7
-20191023031756 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC1C00CBAB
-20191023032601 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC1C810F3B
-20191023041220 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC1F6D731B
-20191023044241 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC2154D00B
-20191023050540 2 6 100 4095 5 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC22C34F7F
-20191023053137 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC24636123
-20191023054409 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC25224B73
-20191023055524 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC25D1FFDB
-20191023060757 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC2694C58B
-20191023061045 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC26B834E3
-20191023061921 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC2738F1C3
-20191023063046 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC27F1807B
-20191023070045 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC29CDC52B
-20191023071942 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC2AFB0F2B
-20191023074553 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC2C984AAB
-20191023074939 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC2CCC9613
-20191023075554 2 6 100 4095 5 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC2D28BCCF
-20191023075639 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC2D2BA71B
-20191023080618 2 6 100 4095 5 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC2DBACC87
-20191023083736 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC2FAEE4A3
-20191023084930 2 6 100 4095 5 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC30617C97
-20191023085843 2 6 100 4095 2 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC30EE1283
-20191023090057 2 6 100 4095 5 E742CC22AC8196AB705E8DB89387F5DBFB15A97C6B3E188CBD4C792BC874928A0148F33791BBFB4E82989EC1F4C5C4FBF002A329190728BFC02AAFD8218102045AF53F8650CAD3E6B98544A1567576B26AD72F6CEBC0F7CF15EB5A62D4678A0E4A0AE868F759BAA31EB27083AAE879248068FAD7FEDD7673689E4C22010278DF2EB37E9FAF353C5A66F0B5916A9812AC91B581B0428D5C9A8D4CEAEAE5B9D11BA3692EBDC9D86C56B0F44CC0771ED405915ED4253A19F58913CB84758666F7D533E2C52E07B06788EE3AA292C9EF6A6183411892166710781DD188F88BBEECE87F6F1CFBADC954D7061B9F0F5F2C6A7754498D868AE526C8F440D1BFAF8F70059A96760EECB594F9518DDCAC1478FAF387D0703A4A57D1A66701076FA15F4E7E9BC6B0407DA00FA1112B6BE13867669FB21F8D8241C11252ECC5F15816FBC447BC0DE3089629EC03B4F14B6D8C12EA1884379BED5C4B39BA1E3D07BC6C4B5295D4629B5E2503C4775B944D5F2617C4D95527E79EC7EA2CF7E116A1FF95EEFF00A79ABAC3D35524D7C64B8D4199381BFC9DEB3BFE19E0AEEE9B2B864FA74F8C478EE5B6693DD7B6F1E87066EEE9CC0E51F9999E0EC914D96BF86958F0ABFDB6EEA5BD347F6A91C6F4FCC4785E924C76979D0309DABA023B44E4AEA5439696F501D58ACE247D49865FAB169422CAA151DB57A5C4EFF392E56467702ECC31091E2F
-20191023150040 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E44442FE9DE33
-20191023185353 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E444434DA83FB
-20191023202543 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E444436C35ABB
-20191023212301 2 6 100 6143 5 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E444437F75207
-20191024004920 2 6 100 6143 5 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E44443C4BC217
-20191024005456 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E44443C62147B
-20191024013830 2 6 100 6143 5 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E44443D4436C7
-20191024020328 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E44443DC27DCB
-20191024022030 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E44443E12DF8B
-20191024041749 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E4444401CCD8B
-20191024071132 2 6 100 6143 5 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E444442526417
-20191024071851 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E4444426F0F73
-20191024093118 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E444445307603
-20191024095518 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E444445A39BD3
-20191024150723 2 6 100 6143 5 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E44444BF198DF
-20191024180500 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E44444F817E93
-20191024182834 2 6 100 6143 5 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E44444FF6FAA7
-20191024190019 2 6 100 6143 5 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E444450947417
-20191024190629 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E444450ACC83B
-20191024234818 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E44445664815B
-20191025002527 2 6 100 6143 5 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E4444571ED7D7
-20191025090114 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E44446188A3EB
-20191025105729 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E444463CF6B53
-20191025125212 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E44446611F15B
-20191025133454 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E444466DDD74B
-20191025164443 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E44446A87280B
-20191025173652 2 6 100 6143 5 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E44446B808D0F
-20191025182518 2 6 100 6143 5 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E44446C72A18F
-20191025210336 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E44446F8C312B
-20191025210946 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E44446FA296A3
-20191025213641 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E4444701DD76B
-20191025214012 2 6 100 6143 2 F67B301557C55AD46F6DAA869BA8D47C6F0427967EA2FAA689023BE705A7BE78E0F15EF3CE6E1987046EB157869E4C7E9B8956C77298C890B27625010664B31A3C2D4108DF8C107452C5325FCF42D35352C5266216132537F79E9616490BB1DAA074F6FE115C99BF54BA7F1376DE63D03548B97DA359494AE445FF444A315672671FF890B4042CA45A76D1DCEA9F1B7805A6A041A0C7B034818030D63D48873A210A7F7BBDA29E2E659CC81FFDFA2C5DB73579A55DC72C97D81490D81E432222566C75B7951EFDFB69FE1411F6A5D3184D9506847EA5C4FDA3EB48A02ED763C1943A0CA01BC097DA347A1E7C0B2D2856E101EEC5718B7374148D9C31AEA79593C404A0D6F623A38C893B7D2A838DBF65DFCD08C4EE41F168928339CC53DD56D80606F865EB4A188F69AA6B4B7E8D66F87B76F75C420DD5CF015A46F6EDED8F173FCBF541AFC74615A2D088C366966F504B185AE363A5A61E327CDE1C95DEA36A4B371D92D757555FFDC51438254C94B4F0BC14D7F5C7B4214F704BDC4900E398A8EAC4A5AD3EDA128CEE6F7F480E79F4090AC08195B58EF86DAFA09B498BD8BCEE3D4E24A947DA115B1971725EE052502826583E92B86333D938A30D95C4C2DFBB29EB9092C282C86D2FA3D738BAE93B1A2A3A9A86E4693C5887577E5B6770928111BB4E4F58F9CA1845FEC6F92337C38483E6DBEA1C05986D7350D1C4CB9C5C5C4FF9B261C8F8B4A543071118A58B5AC46EBE92808B17C740B7EEF556F5258F576E50A3F2890BFBE4F29DE83A1984453D3E1CCCDB9E5C90846FC222682F51E1F3C12F51127A9B42F9F7B90C5DECC63F2C53DA5162B14BFB3ECC1D872D035EE58A3927766CCF3BF9A87B03B1E2FB87FE265B77B41FBD397B12BEAA86424D14440B5896E47A6867D054BDAC00C2DB7AB2BF882F07C7B6AC98CC9937E5ADA6AC48C65D5929E614CD71E72EA57EF5DC6B5BF464629A6A3DB4739AA760C059846C971E6C1AD7260622B450EBF395D2E4D0A554DCF3683A3AD6870838CE795435971B6D9380091F17470348F56E4E8E8EB660E60CB4F20BF89DB8B71E44447026470B
-20191026005042 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E05623363
-20191026075212 2 6 100 6143 5 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E0E59DF2F
-20191026134748 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E15C2570B
-20191026141044 2 6 100 6143 5 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E1634BA8F
-20191026152621 2 6 100 6143 5 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E17BF036F
-20191026153744 2 6 100 6143 5 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E17F17297
-20191026161846 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E18BFBD0B
-20191026183157 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E1B69DDFB
-20191026183823 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E1B80AE83
-20191026184938 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E1BAFB703
-20191026215453 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E1F57BDAB
-20191027005434 2 6 100 6143 5 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E23020867
-20191027042709 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E27606193
-20191027062047 2 6 100 6143 5 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E29A86A4F
-20191027071632 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E2AC3EFB3
-20191027092825 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E2D67AD13
-20191027104355 2 6 100 6143 5 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E2EE2E4EF
-20191027105052 2 6 100 6143 5 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E2EFD8C0F
-20191027112952 2 6 100 6143 5 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E2FC1013F
-20191027134854 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E327D6FDB
-20191027141251 2 6 100 6143 5 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E32EE5767
-20191027160720 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E352B49DB
-20191027164412 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E35E01D13
-20191027165524 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E36100063
-20191027184917 2 6 100 6143 5 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E382743F7
-20191027205847 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E3A93CA6B
-20191027210626 2 6 100 6143 5 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E3AAFB96F
-20191027211813 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E3AE1DE63
-20191027213244 2 6 100 6143 5 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E3B21B0FF
-20191027213714 2 6 100 6143 5 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E3B2E39F7
-20191027221420 2 6 100 6143 5 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E3BD9058F
-20191028002356 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E3E45B4B3
-20191028005652 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E3ED864BB
-20191028014800 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E3FC45A63
-20191028021443 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E40396033
-20191028041626 2 6 100 6143 2 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E42827263
-20191028054443 2 6 100 6143 5 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E44349037
-20191028102149 2 6 100 6143 5 CA8BE2F0F45FB0E6A14758704CB3E994D1CC39121A04E6441CD99BB5147478C39229902EF283CD0F2D7E51EA756E65DF0A2457307EADDDC7715A527708C8EE041DE44AFE8BBFED0C5C7130EF8B89E817469B9768C6C9016C6AF5CD9E6F8563A1837747B61D25872F44D8482C5986C5322ADC7CC68FC4EF025E2CEBB933E78CCBD70E4D223DA4F5F6683F2B7802088333A51F0CEDBA0D15D3B31637778A0F86BE61FDD1392F4CEA58DECFA99D5087F31B753180FBE456959CF7615FCE40B34D0C188B1011C15882B3F62AA4BA89B240B03F285AB0E8AF85C1AA68A127C567E9784B04CB2553AE64CD42BD90F234A86A6D75A2E4EE81343128C786F878C21F60BFDEC0620311448953945CA88637C98E475CF3195404FE19208D6629CCBD307B1B79222A9BCAD27953104E4AF38259A6C2136F82A3A29D339AADECCC09C02ABC0D42A3203CFE7894A1D3CDB5E9D5A7612845279E73D7CC6C7D4D54C2C0AE19C3D1E20354765954DCE9CF70F3CA106B3DEBA6BC882C2575297AA4B98C8E42D8FBD80DDE92F4BF375DD9238AE28337624BCFC76ACE419713B1F7F3CA35D4F9A5565FBC921890A7D652C91AE7E8DA2AD289CB6616BB0F7D3DB181DAA2833F329B38C8E85BA87E19C734C0B77855D89913FF6C527F758FFF3CF33BE405C5C64B1E57E0F4F7EF042B06D871F1AFA181E51ED505622E6FD466705756DE48C81BE86748E337F6A2032C35A88A364A258F39830998AACFF3FA1ADF5960D62FC3D8AFFEE1D7D812F0049EC558DCA9644ED0A7A8BFAB58C2238346F357F6D8649105FBD1C62EB6D3E59E6B3086AEE1BD4C950535303FCE17EB74B764F6D77DDCEF05BF931228DE728001136B56960482A757E3CE14B920BAC72B5C5280EE99BFD689A2439778482A2333979F82987B8C1CA01D894C22CB4321D80A09C164D24DDEA39021F2A6E465138862ECECC2451B83A9478C5728D5FBBDCE0233792B5A27BC7E3E723D12AF6D4A5F6561179D0B6EDD3225F3A80CA5B265672647AA0E4EFBC9DB202632E18B23D57B86AD545668A9B09791FEAF168EC99BAD63ACF8D29CFB4C3E48BF4367
-20191028204729 2 6 100 7679 5 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077C56962C57
-20191029074748 2 6 100 7679 5 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077C5E6F0DD7
-20191029104921 2 6 100 7679 2 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077C601D891B
-20191029115340 2 6 100 7679 2 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077C607A9FFB
-20191029123325 2 6 100 7679 2 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077C60BE442B
-20191029222629 2 6 100 7679 2 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077C677977AB
-20191030071819 2 6 100 7679 5 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077C6D9F6A8F
-20191030072920 2 6 100 7679 2 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077C6DB5BB43
-20191030132209 2 6 100 7679 5 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077C71C9F707
-20191031002135 2 6 100 7679 5 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077C794F4DFF
-20191031064758 2 6 100 7679 5 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077C7DA1F51F
-20191031135153 2 6 100 7679 2 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077C8253C3EB
-20191031201815 2 6 100 7679 5 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077C869AF937
-20191101055219 2 6 100 7679 5 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077C8B9A2CE7
-20191101065855 2 6 100 7679 2 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077C8BFA04D3
-20191101102927 2 6 100 7679 5 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077C8D496B7F
-20191101162017 2 6 100 7679 5 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077C90C40057
-20191102073643 2 6 100 7679 5 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077C993C9B5F
-20191103030038 2 6 100 7679 2 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077CA2EF80F3
-20191103040704 2 6 100 7679 2 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077CA394AF43
-20191103144920 2 6 100 7679 5 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077CAA0B72CF
-20191104025539 2 6 100 7679 5 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077CB128D89F
-20191104104258 2 6 100 7679 2 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077CB5D65BBB
-20191104110623 2 6 100 7679 2 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077CB609F2DB
-20191104113147 2 6 100 7679 5 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077CB6451277
-20191104123416 2 6 100 7679 2 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077CB6E19D8B
-20191104181953 2 6 100 7679 2 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077CBA5B05EB
-20191104182450 2 6 100 7679 2 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077CBA5E4023
-20191104230444 2 6 100 7679 5 F606CDE6712F7C0B69FF0872BAB21EBEAEA36BE53D9E03097D8FCE89594F90ECE8E7F1D6CF9D78821617B32D0D7EE46D8BE6EAB108638001AF1F99329DE3588362EA7677FF962ABC2E4B8CFEAB07C8C88774BE6DD9DD6178CFF6A93A51287903937C9E62F060DA0615DCCB8AFE87A19B185B5B85CC3D6821FAEB3D760AF97903A46B12294F2CDEACF50EC055D68FF2DF84EC8355C0D27565AA1CA5F8517E9ACCAFE804EEF55C63B1EAE4484F821A0B92B9E68EB8A894BBB168286BAD5CE14CC2554424585B15DD70D6CE9F63DAED7F902A818B0B1BC303BF059DF20A5D382610F06676243CA0D30C544F5DE34DC983EB51219B268BC0502423BFA9C03338790B480C61230CE1558D500061057F75DCA5E8509DA30A3BBD93CA0E3D88C8CE0B78FDD9E2BFF8F3CDBF7822859E95F9B0FB1F9AC9A89BD44BDFF8012595DF79639BB49A82410F9EC687B50C5456BEA8B477F7BE5027EBD2F3FE3CEA491DF200B7667EBFF889580E47E89DCC13B841BF958FE7575D8DA4BE8D4BF9EE9908A3C8A3F110E477BA188FE1AFDF611D2E0C8D733DABEE52AECC818530C6C92EE28E0CEEEAF2A984C89F7574B5BDE62FB29C4A232642B21BF5ACAF8D6385CFF2CD4B97C48CF5080229EA4EFCAA046787630A134726A7F89BC0AF4DBD09B9BDAC79CDFD8307D39188A59F9C7BB89B45DBFCF6B3AF44A7F3F2A770DB517F7999E4EBFE0FF6F63C91BA8444B666F2300101F91ADA39012DAA4E1E96C87F1F55CC4D663FC455F57E226C8A1A53720BE73B71ABC6DE64ED339A67F883648CC507DE479CE1ACED66FFFE06829861F40E681B333A1FC00EBFB64512ADB25593BFEF23494D70A70478454DEB92ECC86485288F3FF5DE146AA289C864AA55643F278A3E20DF06CC818AA4EBEE29347131087436C57F82693375B776C1EF5D30E637684DBD17EFE4BBBBF7C14DA4FE4BFC86150553D52792D08C2A5EE35916CCBB3C0718BDD3F631B2458DB029FE32644C190492F7167E9B776793FCA8FDAF35084087FADEBA654ECDC24EECADE28B0420A1152CEEAF14628EF69D516E6074D022AE1E3B9B5260C61978E03CFFD8B61087EDBD2A09C35AD250E3265D72D8B12B4F33F490B417118CDC531349C1EA65CE5FC69B712D4228BC39141C7D4871135157CFDA899ECA2AF93FD11DAC3C5F7E77A9FA6B51092FA5F19A2A087EF03F6D2BE7F669F8E1BE72884AA6581CD90CE74141C5B827B3EB04D1F157549B9807F1214A95D5F07FBD3E47A8413EE740071F456B3780CE2E4F48CC2E499A9B4CCBB4B3D363D1FD73AC4A32F83E673AA460A9CF140994664AF6029B0113F522D45CDBFB23EFA647077CBD2DEB3F
-20191105091836 2 6 100 7679 2 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E0D0129FB
-20191105100933 2 6 100 7679 5 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E0D92A647
-20191105234826 2 6 100 7679 2 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E171AE8D3
-20191106052238 2 6 100 7679 2 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E1AEC5E43
-20191106071634 2 6 100 7679 2 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E1C312BF3
-20191106092936 2 6 100 7679 2 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E1DAE275B
-20191106120421 2 6 100 7679 2 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E1F6DBD13
-20191106122445 2 6 100 7679 2 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E1FA1E1AB
-20191107014126 2 6 100 7679 5 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E28AC4177
-20191107144145 2 6 100 7679 5 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E31696647
-20191107152955 2 6 100 7679 5 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E31EAE00F
-20191107170414 2 6 100 7679 2 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E32F54973
-20191107235721 2 6 100 7679 5 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E37818C57
-20191108191832 2 6 100 7679 2 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E4357C06B
-20191108224321 2 6 100 7679 5 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E458BA9C7
-20191109135352 2 6 100 7679 5 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E4D13F4BF
-20191109143346 2 6 100 7679 2 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E4D7EBEC3
-20191110001842 2 6 100 7679 2 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E542DA06B
-20191110175307 2 6 100 7679 5 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E6046F9BF
-20191110192342 2 6 100 7679 5 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E61370307
-20191110200757 2 6 100 7679 2 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E61A90673
-20191111005215 2 6 100 7679 5 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E64BD2F0F
-20191111221634 2 6 100 7679 5 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E728AB85F
-20191112130746 2 6 100 7679 5 E67A1BA3549A22E8E5008979650D6C7742558513C6C407C4B9CC87E394E8BF9E5DE7248841813BC72DE6BB56EA086A49C69031D2521204BC8EAA0D85B4F2016A4423BF24CCC2A94B7385325A11ADD338ABEDF6B7C444870597F9B05411942D235EBA9CA762F7F2912C1540063C167FE87E0B38B1A4EEC9FA5096102F114577F8D335448B6D6DB022890A33E378EC2D70BE921782CFA0477575E3D867696F5367011BE83025E30AC6173A33A425A9830BC9BD2BC66F561A8906137F68F4F215EA7D228145E4BD5314FDC950CC9CA61523723A9079E728368A6A96193AE3488D48ED7AD61D5B3EA5E4EB6F599963B6B556C0A1D5F174EF0A99F422E665703A6A4FFC588C73DA3D07C287CD9AC5F1065FFB3FE20CCFDEDDC9BA9A39431A2FFA1F94E8B7A3EBD6FBF64BDF9A9C20577AEA1436F08DEBFBD4FB34769DAB061F7B5661E0CB2E5159FF553D7A1E25C4550725EDE6661B633D564BE574FE007177D8C2A54541780D171EB4D2C30768099B2B8F4E81DC8E9A1DCE9BCEE9E23FE7A6854C9DDA08844559A6622257C856BDD221A29A298F840EABECB4D38013FF3403C634C26FA057BB9201D96E0A7D0C07492D7455A213C44978144BAA88804F5DACD544F8F3213F31B552C7BFB9561E63E8E9CDAA1DC427DCB7358C6ADC03B433413C605C34355DFCB2A32788D1D52041957C4C9B5BA9443DC8B6D1E4F0980C4E81607EAADB26D4352BD5823872AA7496A85242A6FD50FEE7DDA4F920ED3A42FAA475936999A5CE55B96F45637AE551335237E71C9C4D8884ACCFF1A48D02999BAF6D38B42BCA344087BF1A43479C10D76E86071D2DF1D68C2E785B5C1B327EC5B112989AA5F605CC3435AC904760EF369D29BFF2C2B754ACFA892A0647588AC306B5CF44A37EDF22E063B42726EF05EF1B2DF80BE136844F0C7CDFD57FF68E66CEFF27D92C0434F292242B086E2CED408973644E9CDFF0C22462400236FD87E03AE69DBBAD4AE3E2213A8888325A16CC3A83A092D1DFB22CFD7AA5C071016862FEAE4735221C4F5F062B6D82DAA38611B0EB0E2C220F2817C50D4B886C0B408D0A1CB00A0E9F4F3CAA9A1414DFB422DFF4309CE6EA70E0AECDD2AA7ABEF84FC207C8DAAC4B5C95DBD46B954FDBE7F0B270FFBD704E7B542BFB87B231F0805AE6D5253C462C0A43B8E7AF7030BA31768E68744E51EBAE8271242834A9CF88506421B918510AD3710395D58A032D176C45FC935DA0510E88F807B7D7E2129980275B0786859E10E849B5C1DC2EFE247398362F2E868162E7BDF241B3749ACDB2BCB2705026F0A40F6E2A91348DFF8CE4FE28FDAA47AC4A5E45C42FC9A4676A0D8E7C1545A7
-20191112235240 2 6 100 8191 5 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C09B051E7
-20191113080333 2 6 100 8191 5 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C0DFA4497
-20191113172045 2 6 100 8191 5 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C12AC18C7
-20191113200551 2 6 100 8191 5 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C144987EF
-20191113222215 2 6 100 8191 5 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C15AC15DF
-20191114105339 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C1D643593
-20191114122810 2 6 100 8191 5 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C1E6B7F8F
-20191114130017 2 6 100 8191 5 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C1EBA7C07
-20191114145117 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C1FE5ED4B
-20191114151102 2 6 100 8191 5 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C2010EB4F
-20191114175356 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C21C7632B
-20191115033149 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C27E226FB
-20191115034007 2 6 100 8191 5 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C27EDDB17
-20191115161656 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C2FC179BB
-20191115163508 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C2FE8BBD3
-20191116013312 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C35152223
-20191116104137 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C3AB548F3
-20191116131152 2 6 100 8191 5 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C3C3644FF
-20191116180544 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C3F1E201B
-20191116195637 2 6 100 8191 5 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C402E471F
-20191117014351 2 6 100 8191 5 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C42FE585F
-20191117195700 2 6 100 8191 5 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C4DBF75DF
-20191117204232 2 6 100 8191 5 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C4E2912E7
-20191118131732 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C54343CD3
-20191118210639 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C57F77453
-20191119125926 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C6021DE6B
-20191119132613 2 6 100 8191 5 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C6059AE27
-20191119133140 2 6 100 8191 5 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C605D833F
-20191119133605 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C605F151B
-20191119174042 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C6292A3C3
-20191120093944 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C690A0B53
-20191120141650 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C6B4934D3
-20191120221735 2 6 100 8191 5 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C6F3A553F
-20191121110820 2 6 100 8191 5 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C75814AB7
-20191121112452 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C759A62B3
-20191122050747 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C7E3D2D43
-20191122111758 2 6 100 8191 2 D57E3B56BFA7F8444B8BF4E425C7CDA8AD8013E4403F9987C70B1B973D9478B38CD2759C98B9E195EE06098BAF739F101F8290E0FCD9DB25C5F5502A90F748ADB2AD6F0A40A38FD44F2EB548395B070B31A81216B1A2B7A5EAE6186C57C6BC574D2428BD62871A3AD9B54E6ACF35DA9F56F2291472A90BC400196FA4B033AB8D3A17C3023E5425052B5222A2755B6F7D4CEA80EC6F2BD26B72A76E37C880651AB32EE51B86B90D23B02290996988BF8767292883CCBE693A8FA065D1CE6F8496F8D3DB5661006B0180F9C020278CF96F36D0ED9242A5139FAE3E7008CCDC9F962338A7B8D41873970B4BAA183B633FAA6E5229230100F9BBD0927B4423F9840DC0544D83798B16C114C6929AF89C0797724635194B25BF53107CB65713FB08214AFBDC05AF993C3F9CFE929A92A52D3C97816C667EB79F8F26F619CFD41C1D792C9BFB825E473E510D4633063312625BD91F22E590CFF97CB5DB0AED2784CB15683C5BE6CD73201F42CD7FA28019BB60CFD088B5B2AC3CCE1A96E01167E0C5042AB744C50230CB8935BDCA020BE2A20E00CD04F8BEF55B64B1E8064C149697C1D313872E29E29931ECCF7130EDC842F44A72B2847BD5C2E438E462E28B47E11235E892690391296FABAF2FC029FD508F71719553335248746C578AF4CAE7AF768D51A5AC6E3D996A3DE66A801FAB6B8E80C66138BAB8167518FB1C50A7BEE0D5001E6F01BBCCAB83B0C43FE8103B4FFEC26CA4C820D4AA68FCDE6EECB04E31D87F3D9CC0C195B74E06F1D01CBD7E0F59CAE1FE3AB92E3AF215A752CFFD564D5BDD7853C85E129CCC25B1052A6A669BCF0AF862CB9E44B360E2BB6623DEA2160A76B9679BBA4B62C698DF07D7E042F4DE85A470832B1D7811B4B0EBDE0A8BBEF1F3F57A7CE6E8A8C4E44CF6511602824ABAA41D7F74CC2037C8477549D00A6A69D3F6A93EE6A9B2565FCAA26FFCD7A0097F6F18DE8D80533F8EAE28589EF4381B3AF7E95F183D2FA4B15AEA21BD1965479B0A604508E14DB4CC0D9288F5062D3DA5C33B0295F6A9D9F1AD935AA51C0F7811D19FFACF5514E9BF5D5A545FA318CC5F6BA875BEEDB9E4953BB2285D391E12AC37DD0BC41871CC9D74D546EABC0B20243685633BDA2020419C3DBF7E945D4359DCF4531C7E74C1B0058C6248E4FA9FC87E098A393DB2691EAF0AF4CEA5F6B5AE6175A3EC913A6B2E92BAB9CC9050F765EAD13669CD564345AD9E1BDE7994C792BD01DF349D1D3C72E3FD3EE91CA3372093B6870526BDE5AAEF2B4E0CE260D37CC479EC8162650FE9FA8677DFCCBDB74EE3872F248780F4197D2E56681B04327447DB13AF873CD3988C2B700E1BEB238B644DD53D814537324B83F47E32D891DB4931B4829B53B3195DDBF79780679FAEB0286B451A7DCECC22E949E9A38464F41F17E6AB426337F7ECDA9C8060C9F3
-20191122234859 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DAF157FE93
-20191123201736 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DAFCEA8A33
-20191124005345 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DAFF68AA23
-20191124051934 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB01DD44F3
-20191124175034 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB08BB417B
-20191124192622 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB0982C193
-20191124193739 2 6 100 8191 5 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB099260CF
-20191126025656 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB17A0CF23
-20191126161223 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB1EB9E26B
-20191126172830 2 6 100 8191 5 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB1F5ED407
-20191126180617 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB1FAB6403
-20191127080548 2 6 100 8191 5 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB2553EA77
-20191127104644 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB2687A623
-20191128121203 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB33239063
-20191128204858 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB378CE753
-20191128233841 2 6 100 8191 5 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB38F8E4F7
-20191129040635 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB3A6C67AB
-20191129112243 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB3C63FFFB
-20191129184106 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB3F9FFF83
-20191129203059 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB4088D083
-20191129215650 2 6 100 8191 5 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB4136E127
-20191130171835 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB4AD7F26B
-20191130173733 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB4AF317A3
-20191201235534 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB56C3B47B
-20191202030655 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB58188EDB
-20191202063054 2 6 100 8191 2 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB59B534A3
-20191203125547 2 6 100 8191 5 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB685D06E7
-20191203140741 2 6 100 8191 5 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB68EF9D27
-20191203185147 2 6 100 8191 5 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB6B3D290F
-20191203211916 2 6 100 8191 5 F4ED1ADCB74B5BB2954322A6646A37DE50F1FEB9359C83B8837A73263FE7BE52044678EE53D4CDB16268F07754FC0C29BAB897CC643E127AF81546E061B8A0E9B357E710DFAF666BD09AE898B40EBCA5A9E77A530CC677B5D019AD2D0292733F496B0624F430F99AE1BB8AF400D2A72CEE17CBAD9C3E517D80039E6A7F6588319FF3BE22BA517530486A4F10BAB6281FE724B0B0FB785D9733B7095245355226D4B653D3E4F7AAF16E63E523A1A6F092919882203281A2A348BE3F5B601C7BC1C35057B021E8916C71FCCFF9A694D4952D89BF0502FA7A1F044B9062514B636A10510DCB953F46596D592887FB782FD24C44A2C4CF4137986A219DDD909BB34A05719DDA26B402302BC6127B46DDD2F93B6E1155BC4F994F7FFE58E5FF3A6688FD14AB60A9DC804A88871236097275E7D47F71F8C9CDBA687BA04E9E67147E80C56FC04184D4F8BC3F1B8CDB659D99D6B8DA26B954C0315BE6552F27DBF56480A3DDCD88B9C5AE487A903F3EACCD53CE09C7D96DB5E77B57123B81E684D7E3AF19AAF7FD810DA177481EE4FE6323B4FBFBBFD694AC14BFBFFDE6416ABB497C00FA56C29D440AC8E7B464600BA71E814BD25F25BC79628F61B01E5CDB5313B31CAA4EAC88C5D9BAA91FCB3CA0C2F7AE477C17B63033329967E6C92DE4AA47C5A1D376FF71D8B88DEADAD8E7D6549DB04F92EADF16047909D5A11E4AE819194D4B11B242990AD47A1CD55CDCEA6D58496899713D410899A744B81E3890C745DDC916ED878BCA835A278E4C95198B06203DFC9F01124F2C77A392868360410D7AC4D5A21A615480DF3CB2BDB11F3E1D2A0E81C59912563C52CAF4CB71039B3A949EE582A3F5909A7853B15B523BBB798C70B8D9159A52EBF8A433A8C8CB2CA635CEA770AEC861D8BEB687335AA775ED7CDCDA49A0A8B1EF6900204225C00E830026A37805E57D5629BB4B646A1CF435AC83A10E98CEC0F756B7C4F487FD714AAD76F662155E3D755FAF903B26581A7696420C4A77A07F10957D89551892813A0D20FEDFFE90829581D1F1C39863207AC1F1E01691BFFACFF3273679CA8241D77F74CC193170BA2CC33A9E9571FFF86412F892396EE936F5EB58A0649934B98479C3306988264D5CA4AF726B3BFBB24FF552A8C1AFEE336B83BC3070357721B3453A13E37341D01FDD779DC807BBA07F26D3372C58BF5828F1A48F3E4D7CF83E629256CBD4ED91BA03EB00D666C3957196F5034D3A91F19FB3E06DA1293B4635A88D5CD49AE5DFA8377C717865B72F66407A83EAA4F6A7077CAC4C220FEBB74B2160A98051655D67403C15E54C0227C63F95F806A0BF2C57D7522272A572F1FD5761432DB53A9CB91EFE65A3E33E090C913EB1BCF45CB9518D818DF39EE8FA1BE8B7338902714CD2EF0B918066ED0573CB6E347908A097F48266D921A6DB6C6CE027
+20210510040256 2 6 100 2047 5 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B6F7F372F
+20210510040337 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B6FC9DF33
+20210510040415 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B700C2C43
+20210510040454 2 6 100 2047 5 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B7052E7EF
+20210510040524 2 6 100 2047 5 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B708A4C17
+20210510040600 2 6 100 2047 5 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B70CAD2BF
+20210510040723 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B716449C3
+20210510040743 2 6 100 2047 5 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B718416DF
+20210510040805 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B71A5291B
+20210510040833 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B71D2EB43
+20210510040926 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B7233C20B
+20210510040945 2 6 100 2047 5 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B7250533F
+20210510040952 2 6 100 2047 5 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B7255E727
+20210510041013 2 6 100 2047 5 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B7276D7F7
+20210510041024 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B7285067B
+20210510041122 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B72EF5963
+20210510041140 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B730BC05B
+20210510041146 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B730F5103
+20210510041159 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B7321C19B
+20210510041220 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B7341D4E3
+20210510041337 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B73D507FB
+20210510041353 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B73EBBAB3
+20210510041423 2 6 100 2047 5 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B741F0C37
+20210510041442 2 6 100 2047 5 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B743B9717
+20210510041457 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B74537023
+20210510041516 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B74718223
+20210510041554 2 6 100 2047 5 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B74B62DE7
+20210510041603 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B74BF7D13
+20210510041611 2 6 100 2047 5 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B74C76FC7
+20210510041709 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B7534B763
+20210510041738 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B75649FDB
+20210510041815 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B75A664CB
+20210510041822 2 6 100 2047 5 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B75AAA067
+20210510041829 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B75B05003
+20210510041939 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B76327F4B
+20210510042001 2 6 100 2047 5 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B7657FF9F
+20210510042024 2 6 100 2047 5 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B767BF81F
+20210510042108 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B76CC8253
+20210510042208 2 6 100 2047 2 C7CE688A891B095F8844E2381248DFAE8FA10F704F18EC478287964C92B6931F4DCEF6250CEE631DC7217BB9BCEDF38B29FBFE1E62C4461F3B4FB0DD872C3D7B1AF59DF757564EFFEADFBCD4529760A9B8F277E31BAF8F986BB5C5298ECF5E0760977111396ACB3782D2F6D91B6059160F28A667B6BD61ABDCFBDA374930FFF31A2620DF9AA6BFE8C2C27E78A8423FDD0DBDAF6D3E52EC80E345D5D64D5F6B20BD8D12E13D415788B69868EBA41360E1C88A25BE04B7E0182284276EC4E3BF2CE45C373C2E43C6B575C2A579209FEAEA885E20C11471DD884942266B9E3847B8839FC2A79F8F1594ADD8A10ABAC9C7881B2CF99D762B5E2E7A0BC52B773A4483
+20210510042307 2 6 100 2047 5 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DB9689F57
+20210510042318 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DB9759EDB
+20210510042544 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBA901DE3
+20210510042605 2 6 100 2047 5 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBAAFDBFF
+20210510042627 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBAD1CA43
+20210510042651 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBAF89D2B
+20210510042714 2 6 100 2047 5 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBB1B9777
+20210510042739 2 6 100 2047 5 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBB467097
+20210510042750 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBB55E393
+20210510042822 2 6 100 2047 5 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBB90099F
+20210510042827 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBB9285DB
+20210510042900 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBBCC8583
+20210510042912 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBBDABFB3
+20210510042934 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBBFE3253
+20210510043037 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBC711233
+20210510043054 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBC8A48CB
+20210510043100 2 6 100 2047 5 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBC8DDC1F
+20210510043115 2 6 100 2047 5 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBCA597AF
+20210510043209 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBD076783
+20210510043220 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBD14801B
+20210510043228 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBD1D92AB
+20210510043239 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBD28D563
+20210510043253 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBD3BDADB
+20210510043313 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBD5D71B3
+20210510043347 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBD9B7913
+20210510043419 2 6 100 2047 5 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBDD144B7
+20210510043448 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBE03F6C3
+20210510043524 2 6 100 2047 5 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBE40DB47
+20210510043553 2 6 100 2047 5 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBE70EA8F
+20210510043611 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBE8DE163
+20210510043637 2 6 100 2047 5 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBEB894F7
+20210510043702 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBEE0932B
+20210510043916 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DBFDE81CB
+20210510043947 2 6 100 2047 5 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DC015B74F
+20210510044005 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DC02F7D33
+20210510044107 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DC0A0FCAB
+20210510044154 2 6 100 2047 2 C9E8F5A2E2CD5EF3BA0F9EEC69453B2B69DC4E7B7A250B773348A24D152ED220DDE0084C99D5F24904BA1D98907FBEB17DC1BA0E347D7B0A370A57CE6AC47D0339B639F4BCD0CF1FF1B10EE95513CF3CF9A912CFBACFBB779B4D696778940E7A0D0B43CADC0908358EA85CF8B1E8E5AAEA96BACFFDA93C9DAF9B717717302BEB039E4A17BBC93CE228E9AA9D35D560B3A6F1C60A7FD610D8449C6C0828464FB8DBD3F328371449BCF34FD693927F63F58047FD190B30EF16B45157C7ABCA21347C12BC652B2A4C5024963400DB5131B67D371691C6C27081C433CA7C158CB99F6E4C89E744EA42018DB79D6FF78BB316B700370B813B81112456D75DC0F49F4B
+20210510053053 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C86B3A3D47
+20210510053442 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C86BCD69AB
+20210510053741 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C86C3A162B
+20210510054118 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C86CC74307
+20210510054156 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C86CD6DE3B
+20210510054349 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C86D19E8FF
+20210510054413 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C86D2241CB
+20210510054752 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C86DB1B4E3
+20210510054845 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C86DCDC3BB
+20210510054924 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C86DDEE687
+20210510055001 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C86DF020FF
+20210510055111 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C86E180E17
+20210510055701 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C86EF8B7BF
+20210510055743 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C86F0C6C87
+20210510055803 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C86F1109C7
+20210510060103 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C86F7F624B
+20210510060223 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C86FAC18FB
+20210510060508 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C870107F57
+20210510060612 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C8703506C3
+20210510060937 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C870B83A93
+20210510061232 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C87126000B
+20210510061957 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C872490677
+20210510062551 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C8732DEDB3
+20210510062658 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C873531EB7
+20210510062742 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C87366FEE7
+20210510063155 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C874081463
+20210510063849 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C875123D83
+20210510064051 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C8755C16E7
+20210510064226 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C87592B08F
+20210510064313 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C875AB115B
+20210510064513 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C875F0FD83
+20210510064532 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C875F527EB
+20210510065000 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C876A1697B
+20210510065226 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C876F8D863
+20210510065300 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C87707C4B3
+20210510065704 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C877A257DF
+20210510070047 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C87830DAD3
+20210510070120 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C8783E739F
+20210510070516 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C878D7A903
+20210510070822 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C8794BBDA7
+20210510070848 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C8795478CB
+20210510071106 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C879A76417
+20210510071125 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C879ABD2EF
+20210510071236 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C879D1F7B3
+20210510071324 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C879EA4373
+20210510071838 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C87AB188F3
+20210510072228 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C87B417867
+20210510072939 2 6 100 3071 5 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C87C51C617
+20210510073226 2 6 100 3071 2 EAC054F0A6595901FCD8F7F8FCC4BA738ED1B3A5EBCBA6F7616CAF48A071E1407283441719C3FE1C10D43799F3BF87492ABDBF0F3B0662504AE552C6B670DB5F75553BAEE273BEFA160C918C0C1039AAB3BC058505CA05328B198C797296B70B2F5F73BAB292EDE06955F59541F73EF820DC7F4BFD4DE54C99F16A798266472540D8819F43ED29390271A2A57785AAD3B8BC142D7F3C5A179D6E4DE94C37DC0D278807119989836DA3A8DB918A2786D41753F774F5760095306B15AF307D86E6A9681950F2510C3FB3FC39820F216EA08689D085A89434CF3D98EB5ABFFCEDCBD0E6AAFE9C9BE072814730678B9082B5B62CA113D9243C83199C940D18D748D64B929A94F68268C8D5B976A32041580B2BFFD5D5FE21A338F65FB1FC494416BA804A920AEF90353F4924D30183908D2C56ECBDC381446CB0F8F4162B3F9C050FF4B226EBFC86D7DEFFB20445255A836762B18183E9F932B8775C21CBECB9C31B64A855FF4D1B5B77E6EDBC31776FD0AD5C23E53603074C118F6936C87CB8ECB3
+20210510073413 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC5861ADE7
+20210510074044 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC5964B90B
+20210510074255 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC59B421B3
+20210510074440 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC59F2A617
+20210510074524 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC5A07E733
+20210510074635 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC5A2EFED3
+20210510074720 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC5A47453B
+20210510074829 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC5A6E33CB
+20210510075104 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC5ACF8A13
+20210510075335 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC5B2E9B03
+20210510075857 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC5C027EC3
+20210510080304 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC5CA07843
+20210510080325 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC5CA5F02F
+20210510080534 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC5CF54017
+20210510080630 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC5D12D9E7
+20210510080911 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC5D77D397
+20210510081204 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC5DE0D19F
+20210510081331 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC5E111063
+20210510081720 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC5EA68ABF
+20210510081858 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC5EE2D9A3
+20210510082830 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC60582ADB
+20210510083201 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC60E0CE7B
+20210510083743 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC61BA35A3
+20210510083915 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC61EDA4A3
+20210510083946 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC61FA1EB3
+20210510084019 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC6208EA33
+20210510084631 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC62F8C84F
+20210510084729 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC6317E0DB
+20210510085604 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC6466EE77
+20210510085645 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC64795C1B
+20210510085906 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC64D0DEFB
+20210510090053 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC650DE7D3
+20210510090401 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC6582AF03
+20210510090527 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC65B4635F
+20210510090743 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC6608EE2B
+20210510090837 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC66237853
+20210510090953 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC66503AC7
+20210510091517 2 6 100 3071 2 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC671C2453
+20210510091543 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC6724D557
+20210510091752 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC67729FB7
+20210510091814 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC67785967
+20210510092259 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC683152FF
+20210510092315 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC68333ECF
+20210510092433 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC685EC3F7
+20210510092808 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC68E5574F
+20210510093246 2 6 100 3071 5 E2F748529B9B801FBAF3AE42C75013A5C4C959A756D496B01A6E1145DB55AA31F408A8DEA8B8573506C76D8AF81C9A3F4D5D4B838D34C30C54D3886448581ABD74D6D95F8B0D4DA21A8E3C6D127657A93354E028D65AC9CFFBCFBD0DEC0EA4F7CBB1018C9618612FB2A5837631AFC614AD2D5FC45EC872EC8816CCB96841A4DC14307159F83F694C90472DA3BB20E9EAC91D1F21770CDC6A037855520D80102005651A54BF12D9BAB8ADB4149ED37B5BD851825B596887DC4E47E55FC0D7B3AE7FFA43F95CCE340942FBEC7E593A16AEAC11CA1136902A2917BC096E8B16CA28D0AC2A58B46DA69B9908CFDB5DC16B391B4DD5C1A8346DB2CDB22447E44FF1567D85B90CD8016029C33D9DE2C992AC73A8155693DDE84FCBB760D88FEA847AEB13EF8058E11E81A7ED0666794272E362F60EF252BD5E3890D85EB6297F99BFA82A7FA94F33EC9804D02E50C56C7856C7B923987825C79A22BF9188AC61E936AC48A40B73EBE61C1C8724315AEA4D1E5AB2889C2251F9A771493955AC6995B96F
+20210510104920 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27EC48D7683
+20210510110208 2 6 100 4095 5 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27EC56E987F
+20210510111200 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27EC618B3B3
+20210510112429 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27EC6F9E69B
+20210510112617 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27EC7137A93
+20210510120850 2 6 100 4095 5 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27ECA1DD60F
+20210510121344 2 6 100 4095 5 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27ECA6D1937
+20210510123540 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27ECBF2F10B
+20210510124120 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27ECC51479B
+20210510125020 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27ECCED89CB
+20210510125127 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27ECCF8FDBB
+20210510130049 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27ECD9C8A1B
+20210510131341 2 6 100 4095 5 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27ECE7F859F
+20210510140804 2 6 100 4095 5 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27ED25225A7
+20210510140916 2 6 100 4095 5 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27ED25E3747
+20210510141423 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27ED2B414E3
+20210510144848 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27ED519CD53
+20210510150859 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27ED68073DB
+20210510151356 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27ED6D0558B
+20210510151823 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27ED71A5973
+20210510153129 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27ED7F992C3
+20210510155953 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27ED9EDF273
+20210510160542 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27EDA4F6463
+20210510161006 2 6 100 4095 5 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27EDA97EB6F
+20210510161446 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27EDAE44433
+20210510164007 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27EDCA3DB53
+20210510164752 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27EDD296153
+20210510170111 2 6 100 4095 5 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27EDE0FAFB7
+20210510171053 2 6 100 4095 5 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27EDEB6FD4F
+20210510172049 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27EDF621333
+20210510174942 2 6 100 4095 5 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27EE15B9E07
+20210510175641 2 6 100 4095 5 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27EE1CEFE0F
+20210510180112 2 6 100 4095 2 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27EE2138F1B
+20210510180610 2 6 100 4095 5 E3508586273EAF882533D9104A0F6FF5818343120ECFA2DF8002402FEA175CD1C418C3CBCE3B8C3B8897FA169C9C9521399321A353ED16DE7EDFD5F28F3F8C1B5F52F368C463B3A1AB5CF5816666973A70FA756A6A2F70313D2830D490541C09F40E7ABDCA7EE76A625F19B87D4336196CBEBEB5491E4365D7DFDF56384A3DFE662628171820829B5628694A4B4915954CF89391F3C06D9A4DF618CD54406A1198F4DF74EA2DDF55244076A5BD9295DD516B9346A98EC225F16968CA804B94F2CF67B0A4CC23A679766476CD8033CA3532230AB83092D78AB138653BAC3FE96C2E6A91387E2D7263B72CC0FEB5443233BD5C137351A4EEC65954845938DE8137C0E3F70D9932E18E4C771BD0ED3D11CDAF4EA9745D3C2C8C32E2F4C7302425A96720F939C9A32BA9475EC974D57326605F5B0402FD6431096AC965246DDEA5AD8B2B0C24A86FDA4CC9397DCE101DF441AEC0FB887CB17F61A25D2C5945BA2DC45766E939CE1210C5D0E9A8BD229EA308E995B6A99164BAC0F3985010C4AC7C36F0BBB3118A17FB1963E865AF49FD77FB4E1BA3D9551C3FAEA77CCD7A7D588294DE9EA3B8DB6A8CC98DA8C567CDAB709A287F5D53453267841E6113B3A06DF01038B6A83FA6AA4A645BB43D276B71C6EA65A98A4E9C839D38CFEDCE176C5480E8BD8AEEAB20FC1C89B889672D980C5C121545CFD4BECECE53E9CEE27EE2635EA7
+20210510182139 2 6 100 4095 5 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D4CADABDF
+20210510182246 2 6 100 4095 5 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D4CBA2FDF
+20210510183239 2 6 100 4095 5 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D4D6A3817
+20210510185138 2 6 100 4095 2 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D4EBD743B
+20210510190703 2 6 100 4095 2 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D4FD39563
+20210510191012 2 6 100 4095 2 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D50038993
+20210510193403 2 6 100 4095 5 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D51B59F6F
+20210510193504 2 6 100 4095 2 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D51BFEACB
+20210510193712 2 6 100 4095 5 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D51DE6847
+20210510200016 2 6 100 4095 2 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D538092BB
+20210510202408 2 6 100 4095 2 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D552B8EA3
+20210510204717 2 6 100 4095 5 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D56C3E03F
+20210510210552 2 6 100 4095 5 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D580CD59F
+20210510211223 2 6 100 4095 5 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D587C16C7
+20210510211607 2 6 100 4095 2 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D58B825A3
+20210510212131 2 6 100 4095 2 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D5914A563
+20210510212930 2 6 100 4095 2 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D599D3C2B
+20210510214640 2 6 100 4095 2 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D5AD02FBB
+20210510221404 2 6 100 4095 2 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D5CBD7BCB
+20210510224430 2 6 100 4095 5 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D5EDD3847
+20210510224732 2 6 100 4095 2 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D5F0BA233
+20210510230510 2 6 100 4095 2 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D604292FB
+20210510231041 2 6 100 4095 2 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D609E882B
+20210510232117 2 6 100 4095 2 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D61508923
+20210510232533 2 6 100 4095 5 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D619565D7
+20210510232612 2 6 100 4095 5 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D6198BB57
+20210510235513 2 6 100 4095 2 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D63970EA3
+20210511001630 2 6 100 4095 5 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D650D625F
+20210511002532 2 6 100 4095 2 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D65AD01CB
+20210511002655 2 6 100 4095 5 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D65BD0E3F
+20210511004533 2 6 100 4095 5 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D6707A94F
+20210511005704 2 6 100 4095 5 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D67CFB01F
+20210511011635 2 6 100 4095 5 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D6922CFE7
+20210511012416 2 6 100 4095 5 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D69A4C92F
+20210511012915 2 6 100 4095 2 C0CF9D192A5E67E12DB4EBB35F3DD5A93041B217DDC24746828F760867A58487DCC1318CEB5929A76AB776A38F78415D03207716AFB66462B964A8B64E26D54306DFC888AF824BD68D46FD93EB19835F5CA576CDF7D57281B5A2D443CA10B94C9D091680FAE8AFDC9E862E7B8AA8EB9C5964A7A6DCF33D07735325CDC0AC2E0CB1AD72398FD23D9F375C766E55060C7E9556F16933363BD73288755FCFBE99FBEF5FEF5CDBE525AC7C1AB26CE56316568FA790082931F4015CE0BB432797A80617BEF82B448D8CF568A2EEF1CC594A4CAB3FAE7CB97866833D9BD646BB4A6850AAC1D6C8011C486C9FAB4AF5FB7C1591734B3D9FB3F46E6A07F61D1AA78B19B4C96AAE67ABCDC1218D205277054711CD88C39D93913AAFED002C96950852971C044779E8C44452321A72B50802658F1E62759B5155AE21FDC3F0CBFA1BF06E35147ED4E328E1D6FFF1BC67CE4EC4D7872797759891D74E53BD496BD7E54C6F28E8E2D60E0CC5381E136465C551BA03B91D112F50F4F84208C2AE35C7CE712F230539E5CE5211D87C56074EC6E53A0A1FFB811B9580F7045D14B89C0E6CEC5B12834317944BB2D743926BD2EFF4D8CD19E7A85C58E0CD4BAF7D7915F4A8EC46CB20FF3B82ED5C8D30F5A4CAA07E0C8CCEE173FC59C3444CEB672220B98F8065A9DD5244BAAA6D44347100D2D4FABC8FB7E6746848E0E9CFD2C6AD701D69F74C0B
+20210511102814 2 6 100 6143 5 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056C4ADADD7
+20210511104622 2 6 100 6143 2 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056C75C31DB
+20210511105027 2 6 100 6143 2 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056C7F679E3
+20210511110103 2 6 100 6143 5 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056C98961DF
+20210511113326 2 6 100 6143 2 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056CE694ADB
+20210511113553 2 6 100 6143 2 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056CEBCB733
+20210511120155 2 6 100 6143 2 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056D29CD07B
+20210511121150 2 6 100 6143 2 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056D40F2B2B
+20210511125715 2 6 100 6143 2 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056DADDC183
+20210511133230 2 6 100 6143 2 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056E00C0173
+20210511134118 2 6 100 6143 2 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056E14EC08B
+20210511135454 2 6 100 6143 2 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056E34379F3
+20210511140822 2 6 100 6143 5 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056E531D6AF
+20210511142133 2 6 100 6143 5 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056E71D2267
+20210511144054 2 6 100 6143 5 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056E9EE160F
+20210511144259 2 6 100 6143 2 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056EA31E3A3
+20210511144958 2 6 100 6143 2 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056EB339A53
+20210511145731 2 6 100 6143 2 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056EC45903B
+20210511150937 2 6 100 6143 5 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056EDFF14D7
+20210511151422 2 6 100 6143 5 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056EEA51A4F
+20210511154856 2 6 100 6143 2 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056F391E0D3
+20210511160239 2 6 100 6143 5 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056F5802B47
+20210511161337 2 6 100 6143 2 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056F704FF83
+20210511163831 2 6 100 6143 5 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056FA993EF7
+20210511164110 2 6 100 6143 5 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056FAF3096F
+20210511164534 2 6 100 6143 2 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056FB84285B
+20210511170505 2 6 100 6143 2 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7056FE524F93
+20210511172712 2 6 100 6143 2 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A70570166A98B
+20210511174145 2 6 100 6143 5 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7057036F804F
+20210511180342 2 6 100 6143 5 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A7057068862E7
+20210511183715 2 6 100 6143 5 EE2D1C3A0CC149C6675914AEFB8A3B27C939CB721B7D7D2AECDF4464406D6B59DF4C01ABE292F37396B097215BCF049F98D5B7CBA342EF5DFE31668084E83E783AC5C21CB152C08EE0BBAB4CC8F261AFD378F97D5044BC6BD3E555ADCF508ABC26E4CAF8D0B84EDDA7E78B56B89A497BC4D5A1D5C14D1A535777D4BBA17540B64F3E2695C5B134275A2F94D1388C0F666573454ED38B3E0CAA04BF5551662A429B54153795935493FE7E3C8130EE4568A278C2FF362D070FA4D10462B347E382EE340DF1EBBDBFEFAD66AB4B2296E982EC7F0947F6BF7845E8C40F9A7B4934727781E2D129C2E055227C3CD063BBFF14DE2958D6B4D3D3EF54ECA8757C3D102B98B6C97BE8087FE6B8ABC4B7D61AB491842E37A53890081C73359B4B878570BE3B30E557B819DBEC06F1291965419B7EAD74F1ADF900E771781024B44E5669DDA88FD9C62496764EA5CE3E791EB4CCDA3E4B665355C9EC92EF18046331332886B79DC3710C36F02D2EB260246AE83459514EF00FC5857CAC8562D4DD522FA4575ECD1BACA7313A1C91F72863DFC8AF0732C9025862525CF33E5EC545D356C620C70F16D2BDD22A9BD9A25469D21C70D437FA08ED36550A2EEEF3545EFDC5A0C0FCC1070A99B2D5EFC1A32D764AEE21DC38FD6086813C01F09298B41B3EFC7F34DB201EC538901C8E05A3B3295519042CF631226BBAF9A9F8A3C4BD6B00E24CD048A14ACA7C8B9EC1C1931853909EFF8B1FBCA46C9CB9E42BE7253E7F25A97C6D50E970EF8CEFE1C70C8A3254F5402F3DCC62A5A34B477A8B452352B6CB2BFC1F372130DBC4960DCD20088DB50B39998ECCB0CD2F797F7267529DB9A63B7BE8691F9B6155EFFAEEBDB8EE7FCA2EDD9DCC92B5DDCF536E87DA064010A15CA505885DEC6499E4B1408580A3F854E1C50BEA96D4B47D9022B004F426F1F69C7580573F60BA80045BA799FB486C1AB3E363D75DA7C2BE5E256001E728B4850BA99184068CFF7A87B25C95F43E17B35BEBFA4711A1307EA545B1BA97D13F752EB7CD6F42BA4776098D71C02E4961480D18AE898D2EBCD61E897041CB1A70570B38F77F
+20210511193129 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FD7E2FF33
+20210511195502 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FDB6A44F3
+20210511195827 2 6 100 6143 5 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FDBE676FF
+20210511204743 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FE346C16B
+20210511205051 2 6 100 6143 5 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FE3B37BA7
+20210511210241 2 6 100 6143 5 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FE56FF4F7
+20210511211006 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FE685FDFB
+20210511211804 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FE7B482E3
+20210511213559 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FEA624573
+20210511214955 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FEC6A1563
+20210511220820 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FEF28F693
+20210511221550 2 6 100 6143 5 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FF0410367
+20210511222301 2 6 100 6143 5 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FF14E2BAF
+20210511223017 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FF25C4F8B
+20210511223717 2 6 100 6143 5 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FF358C9EF
+20210511224022 2 6 100 6143 5 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FF3C5C0C7
+20210511224934 2 6 100 6143 5 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FF5128EE7
+20210511225354 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FF5AC9E43
+20210511225504 2 6 100 6143 5 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FF5CE8FCF
+20210511230424 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FF71E9D43
+20210511233003 2 6 100 6143 5 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FFAD91657
+20210511233554 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FFBAD309B
+20210511233732 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FFBE1CC5B
+20210511235930 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E297FFF12F2D3
+20210512001430 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E298001373093
+20210512002303 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E2980026463FB
+20210512004700 2 6 100 6143 5 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E298005D412AF
+20210512011719 2 6 100 6143 5 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E29800A1EF6AF
+20210512012230 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E29800AD88A43
+20210512012724 2 6 100 6143 5 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E29800B84DE0F
+20210512013230 2 6 100 6143 5 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E29800C3AA1EF
+20210512013650 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E29800CCDD483
+20210512015950 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E2980100A0E43
+20210512020847 2 6 100 6143 5 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E2980114782B7
+20210512022553 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E298013B2C213
+20210512022729 2 6 100 6143 5 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E298013E47BAF
+20210512025425 2 6 100 6143 2 F58340194C3306C216EBA34FD995EAF9AF7B4471283E848F4B029734B8BCEBCD8E52D560FFF982CE43FF8B4743C8048BC6D4338C8B93AC9F00C5A9564A840146DE9539AD56551E9187BFC36282EE41C27355F3620B33561B868295222A693A11F5817C1A4306DAD1071FB2D38DE9462DBC4778784F4BD5B27F2FD173C360611E6A21FB82A494BEC22F4ABF1F5AA692B784E15FB737684C0ECC5B8D55FD023C52DE35464CA1AAA8F3F949F1BE6C194CB7C0DD0E5BA261A216CFC40D7DEA492929D777F6B8636A4C05D58652836E70E5956173BFD976CF08406210630C4489534639053F069285A6E55B851423BB3714647681FB05D545F941E69FE5756C500328991387212418E4C54146FBEF4A6D2481DE817DCAE3E1EEDE8E617357630B734FEFD566BB0338D8EE564F35518E59AF81F67AD190E45906A0832515515D6CCD73DE76FE730694CEED007F333DB1F6F9A026655F950751EF85AC1E571A3DA7203D1E53D4D93F521AE1AD75360DE1AD187EFE3A396F40AFED9C7797681A857003A7EA20C2203D2E40419253C6706FD30EAABC972CAA9C5C97B48DC734472D310E0DEE896862407E24A243EEE1E02309A6C7E1E53CD953B93FF54283ACE51B298BB1C92FF0A172948EF0CF8D239A5849D8E3D7AAC4486FB746501F3318145B042E62CA6EB70544E31581687DD67D8AD73FFB39DD71DA00E7F3738890D65610CAA049A5CD99AD928F98D3CFBD9A706E8908A2F51712B03562CB057F99431E0746B98DEE0D367DFC93CA546E26A44A72F47122FABCA47900D76A42B29C9160C46B40F811A1B8BA8651C7CEB1200DED520709D9CC0B21A20C9519084DA66A91158CE7A82674374580134EEA025BB0185807DF2A5B1EDEFEFA8D247A84B787E2597F8BF72ED6F570F32AACA50D10E94DB679FF68CE35AF77537EA4CB7928F7EDD5CABB65E32C0D88FACCFC51C2146BF3FDA433B76F09234552FC069312C38677AD95D501AF829B0A1484FEF9A2F804F0ECD4990079B66568956C34212CE0E483CF7C78D1E638893082826C15E7CA78004D04AC95EE36ED5200EBB74FA39E2980179E503B
+20210510215238 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F39D65FCF63
+20210510222355 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F39D8F2D76B
+20210510231559 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F39DD6E0D13
+20210510234158 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F39DFA06E23
+20210511000641 2 6 100 7679 5 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F39E1BC772F
+20210511003255 2 6 100 7679 5 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F39E3F4AA7F
+20210511015501 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F39EAF7F0CB
+20210511030805 2 6 100 7679 5 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F39F104A8AF
+20210511031420 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F39F182BAA3
+20210511032555 2 6 100 7679 5 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F39F276EC07
+20210511033918 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F39F38CC9EB
+20210511041948 2 6 100 7679 5 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F39F6EA1CBF
+20210511044846 2 6 100 7679 5 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F39F9459AA7
+20210511045936 2 6 100 7679 5 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F39FA227747
+20210511061456 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A0049A573
+20210511070958 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A04A6FA53
+20210511071633 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A0529E6FB
+20210511090443 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A0DE2A39B
+20210511091529 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A0EBA9D9B
+20210511092043 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A0F1F1753
+20210512033258 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A16919EA3
+20210512055407 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A217F863B
+20210512065219 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A2603970B
+20210512071046 2 6 100 7679 5 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A27671DBF
+20210512080928 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A2BE5B26B
+20210512082250 2 6 100 7679 5 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A2CE9961F
+20210512093942 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A32BF8C6B
+20210512101658 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A358BA32B
+20210512111206 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A39AF5083
+20210512111445 2 6 100 7679 5 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A39D9B197
+20210512111520 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A39DC61F3
+20210512120145 2 6 100 7679 5 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A3D4F7B0F
+20210512135337 2 6 100 7679 2 C260CF005EEA851908A07073F58C88D37464F6C4353E3652C60C64BB441FAB9B7FB9F6CBB9D8073D3FE935B70EA1F508B2AF0E89899E9B6FD2B0E0583386A56CDADB39C1E362175A28F278B43A478B8506B1592C5A1DB8F33CE21C43CC5763DE1218C349755906B8D975B9DA963936BC01F7D79C5928C25E602D5B838892C62FDD61FAD8D0E189A70EC5891239BF69A75C87ACF1DC8DC50B359A9DC624FF7F92627B5D29748D84549AA6A831A35742E579A206F56DB0AD497AA834B877538C8045F3EE38A189AF9FFFBFC36FA4758EF1334DA487353514C0C406DB6B38E9327895D73DA4E92042EA6880336392E7E8342A1A7526816FEC68E95C995C9388779636AF8A45F54274EBDDD439AA16EE284FAF1E5459C99372083CF1531730F0354BF7E9C0733A3E785E82D99D270870B97D303F2A968C1469041D62277A14DFA2B279991C7E3C45DFEE93192650BF89D46218932FEB1C357EFA71A7F669F42FA4417F7053AEA70D43646CFDBCF7C05A1ABF53D1B5CA701BB6281097C600F951EDDEB258722C6EBA5A663BEB51CDA38D36584D6566BA1878558A7B2D32B28675D1FB2463C8C8AA5CC9CCBD733F3D741BDDC3F0F9532AAA1BB6E039F59B3CE4E5566440DEABF306861EAC945A4DDB2BC7E1B4096D92EB6901C7B83EB8980128935FCB70E82E855BBE41A9438BE84ACC738F818E5E3EDBA0AEE97CDB1634BABB6B1928BB43EDFB053DE5B3B4F0194A4D79D2EDB949D94B197F5D9406AAD368D5EEC0212A0BCA174F2BFFAACFAF2C51AE1F39DCDD849B04C0AE98935C80E62F63755F9B740343A28A5A7B93D8F5FA63E9C322BF46F484911A3B5581F9039F0A930E77AF641EEA0D1734D59B28B13280A9641382D3E489E069F2D659491F261B5FB7B4B7C7AE823D3C426FDEFD75734AD97DC4359E30BA7E99E073D8D6FD1C6B0F01006F33C829528E46565CE86F781228E2D22D7A5AA4C9E6B53DDACF380404CD9D2B2CDE31C6ECA679AA6A997AC53F9E9A429BFF636A008488447622ACFD6754E17048D0E7F7DF03CE0DE64F9FCAE47A46718D8212D620688A598D3B6AFEC54C762D4AE8AA0BA7B1AC97B8F9766BAF71EAE16D5E2B5614AC4FA5E20A0BCD622134AC7B08E00B8020D580F2C28CA1D15BDA1981CCE0E0AB5CDE942DFCC578EFF0C250B874E638705294A00724F9ED1329DA93179CAA869EE4BBAAD9F29993945745A5116840906BA4DCF9E303CE0947D4FD59C7964CC001882C001FB188697652B0A949624A983DA2099443191F6DD4EF89B705CCC825FC16C4AC5FD63D932901DE28AEEAB0DF883F44A6F0923B54A9477A3B521D8E12DD10453931E00E9F3A45A535C3
+20210512141816 2 6 100 7679 5 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979EBF1F48AF
+20210512151944 2 6 100 7679 5 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979EC46EAC57
+20210512152457 2 6 100 7679 5 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979EC4D2E37F
+20210512160220 2 6 100 7679 5 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979EC805627F
+20210512161859 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979EC96E198B
+20210512165622 2 6 100 7679 5 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979ECC946B97
+20210512182636 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979ED42A027B
+20210512183805 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979ED519CAFB
+20210512184521 2 6 100 7679 5 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979ED5AD365F
+20210512185310 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979ED648AE4B
+20210512204010 2 6 100 7679 5 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979EDF2ADBE7
+20210512204459 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979EDF86656B
+20210512215034 2 6 100 7679 5 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979EE4F3F8BF
+20210512215957 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979EE5AFAD1B
+20210512232130 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979EEC537383
+20210513002903 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979EF1CC9B5B
+20210513010529 2 6 100 7679 5 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979EF4AF06D7
+20210513024603 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979EFC954793
+20210513024649 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979EFC9C854B
+20210513034549 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F013F0FB3
+20210513035644 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F02144FBB
+20210513040521 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F02B7D0AB
+20210513041837 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F03B639A3
+20210513051930 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F08737F53
+20210513054050 2 6 100 7679 5 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F0A117EFF
+20210513061420 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F0CA24113
+20210513062114 2 6 100 7679 5 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F0D21BC27
+20210513063330 2 6 100 7679 5 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F0E0CA30F
+20210513071712 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F1165FA43
+20210513072642 2 6 100 7679 5 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F1213296F
+20210513075016 2 6 100 7679 5 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F13D7F69F
+20210513080859 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F15405513
+20210513082937 2 6 100 7679 5 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F16D0AEC7
+20210513084916 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F184559A3
+20210513101622 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F1ED0663B
+20210513103219 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F1FF64A7B
+20210513105336 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F217BF603
+20210513120417 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F26CCF6D3
+20210513122242 2 6 100 7679 5 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F28222B57
+20210513122833 2 6 100 7679 2 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F2886B733
+20210513132056 2 6 100 7679 5 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F2C65CDC7
+20210513133945 2 6 100 7679 5 FAFDEC5D38380C2FFBEDCDA1262E4817F274B6544BB0A1904CF571375327EDF0105410A3F584F9A15982937EB5A64E30206DA90D66B89BF48EC74E7F40FB957673193875E02B88101A4FE81C47EBCB8451386AAEC6EA69F967310C79D8CC71BE07F669C3094E5F2CD314FF0FDD08256EFDFC03EF43C4704684CEEBBBFC48D48C920B2AC3CC15010D7EE49049D52B12E6E9228BF0482C174747EA40E558D88CACA9F143A496236C120DE560FDD7B2A1175407D333103C025E8EAE424AC5BADA1A354428B451F594BE605000CA3B2773B2D91FEDBBAF2E58DE2F03461A9F8D90B84209F66D7203E92774AB5B83809BAFFCC8D32ACB1B0AD4D1C2D37CED00654FB7517A56FE35CD364967D541D336C0E2CF96303B3BD1FBBC12D5DCF3D8F343BD2DD0EA3B5FA0062DC9A426A36DD27FD9C8E76DBB7FFE97BA3B27BDE53B017D7C9DFA6A4354FC95F3DAD99172290423EB507B574D6CEAF38A4AE227FD44541A29560020EA2EC10C5213E1EBC7A686AFA770A09C28E0D1EFB46AD409D2C58B8A4EF2E740957BCE903FF63D0B5E6BCF7E8C2B8F85DB93FC96E78BE2002603FF9AC2ACF368269FE034D6A5F8BFC6249FD140E85E9435C8B03D9390F1D0FD44519C21D174F7901BAB95DE7C91A1BFB9EB1079C584A71392A72768B2C2748145835AE7A5509B3C59539F46B5E0DF6955B84687C454679C9D87198605D78D1B551F502A5ACD915F55C919763C2F1206A0ADD5F651031A76EA0D102D064CBE24F919D3CF333D1EA0E89C1CA9E7D115802FC38757A50C97849D41E03C5F1EB8485CDDB55464E44172B0DE3D4F94A5AD01ECE4D70E17181225418F4205ABA526FA1D8C493749243D626C1D6A3170AD9D7DA551F3642229428803E81782D49355CB6CCEE08AB7583CA3A73354F2942BC6225E07788E542B1E2A9B46724D8A8EE0BE6F79CCDF78B10FC78FF3E15FFBC2EF1FFF4F53A328C7850BC0DAF358823712FF3609B981377D64FD274C578FFE92A6AE74F6F6A37907BD6B71FDA8C492C15BF9F820360709CFE9C5DFB03196120DF85D7D730DBA4CDFC36F2760227A5EAA27AA255935616A3833609B890B2445FC82D7A70B798DCB71E7C5B868AF06577FDDD034B63FF8A5CEEE3A1BBCD4CC61AF7A21D812E5987B35EF262FCCDFE85FF02E21E95C20C66357D8C813C672AFF03D9B4023E94E4397596BEA7F642D14DDA48D455EE0EBC7979D7AAD8994DC9A0DB84F1EE247C71E3D3A5626455CABC9C91BBAA98E2DD96EDA9EC0CDE2130236907A41D227CC515E1B139D278BC9F1DC231BDBDD76C400564D3200B2F61980B679BE9D8BF9D37BA5C0CB681E5054431A61CBF3979F2DC4BF6F
+20210513144224 2 6 100 8191 2 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB1974BC3929B
+20210513153319 2 6 100 8191 2 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB1974F77AE5B
+20210513202423 2 6 100 8191 5 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB1976458B21F
+20210513231705 2 6 100 8191 5 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB197705C37B7
+20210513233042 2 6 100 8191 2 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB1977149F50B
+20210513233427 2 6 100 8191 2 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB197718133B3
+20210514021221 2 6 100 8191 2 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB1977C49F803
+20210514033618 2 6 100 8191 2 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB19781E711FB
+20210514034136 2 6 100 8191 2 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB1978239BC2B
+20210514061321 2 6 100 8191 2 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB1978C43CECB
+20210514081550 2 6 100 8191 2 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB1979429D64B
+20210514112414 2 6 100 8191 2 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB197A0360BD3
+20210514115310 2 6 100 8191 5 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB197A2059F5F
+20210514125653 2 6 100 8191 2 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB197A6070053
+20210514135322 2 6 100 8191 5 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB197A992D4D7
+20210514152842 2 6 100 8191 5 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB197AF853A37
+20210514153107 2 6 100 8191 5 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB197AFA14327
+20210514162047 2 6 100 8191 5 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB197B2B7330F
+20210514163234 2 6 100 8191 2 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB197B36A5C3B
+20210514173058 2 6 100 8191 2 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB197B701F873
+20210514181258 2 6 100 8191 5 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB197B999E087
+20210514182942 2 6 100 8191 2 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB197BA9B3683
+20210514191337 2 6 100 8191 5 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB197BD4793EF
+20210514193708 2 6 100 8191 2 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB197BEACFC3B
+20210514205734 2 6 100 8191 2 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB197C391340B
+20210514221328 2 6 100 8191 2 D352935F33D9BC205912B919A6C5F18F76C30A32F6C0390249B48383BA4F31098BF5B6B2ACE6A745344840435A6C9A0DBF8E268F0463420452610E9A624590DC2CD57490F709DFFC5A54630DE486C73DB3C377B87C919F90BA88A7B41627351E6BEADBA605C2C625833BB95E9F34892A5D15DDF216D1A549FCFA819D7567D99015B1C3944254B87680222859779EA64C26FCEF82F34FE28E765DE3DDBCB9B3664E7896B18B93B9AA3A69944E8CEB93C18F671E2A75D6C1061B23AF8B913911A73099EA5B0F527C054B8A71B335A65CE680F02DC58D27FDBBA83EE263DD9E171B190F1CDB173BF56BB93407074B1899E8D59832EF383BCF6FB145E0F8A4A7484A2F8F4178D0A8DF9B8B920FF1250BF88BE770FD43D7EF2F4B998D86628A676173384FA95CB6B8A2599F8D5BFAA9E7C025CF29A9E1A8818B90CF2568CB8F3C003BC22B873374ACEF560B114B6B3EA0ED1701CE77A34E2723FB377BD67D480E3BF6A4E71763ED85C4E5F034A8E1761B1424AC67CFD1727157A43EEAD2168622F43967A4494E3C3D92E41EF47B7425D13D746CF617F9BB0F7CF04C093261541B6BAD54E3ED418AA1044C21FCC95B3416E6648FC576AECA4A82F2E69CE017A982407FAB0B656B56933908F1FD739686102F68805B8C605CF88952AEE1257382DE39D777527416FBED01472FE9C947AD58968D7FF2847328265584C2E93F7DF92CA891122AF48B9549020D2FAC44913C2DB5DAE20434E477FC5AF527E3D16D13B5586131FA1CC6AB1D522A1EFDA51B84D82BCBC0E76F00E0C790A9C07D0CD81088A6E972BB453B0D72AACF78BE9506B25301A473C0F4E6DF46B6517C73D9809F5319DA70BD22C0C17D90A0A26080E262D9DFB50B21AABFB60D76E655B78B2C4A4EDE0D32CE1BBD3F05F49C12B30DA10A13BAA95F907A1306F4FAFA251D8F6E16B6A5EB177D7777FFAB5A875B3D27D250B496B3EDCF818020A27D1CF30EF135AA50CF05B70D1FBCFAB92C7D0CC17E3AB813D23233BEDB187FAB1406BB9397760F905658A124923E6F97F947EF88572CC3F50F16FC716DEA622F9878462113A5E43CFA165D80B531843CB024CC310FB4FD80788A67ABCADDD99BD5A26D1FDB72FA5DF44C84085D7EA30393ABA8E7CB659489DE64CAECC4E2E6779E80CAC156B5957C30B89F073E97BD013CE3E7D260917C1B3C46F6AF0B77A2109E7A81DBB20745B4FD4B33BCC08FD30F554C5EF9B6E69CBD225A498D2D51CA440B83205DF7AE9020AF2595F3CC648907EA05C2F4063C835606A4598A7E9CF67710332A938B1FF851A6697F9A38FFA2CCF2BBD6A00F8437794DA285A8E298CCF2D5497DCA6065D8E0AD829172FBF4D10F75BE58F97FB2D272DD9B57C5659910BDF70D78C45FDFE135DC75F8DBB69F78EF068CBEA5F9FC8940D45AB9928C9002EA165CBBFFB197C828281B
+20210515004609 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7B7D0AF33
+20210515010402 2 6 100 8191 5 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7B90F73BF
+20210515020359 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7BD3DCDAB
+20210515020859 2 6 100 8191 5 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7BD8C099F
+20210515024607 2 6 100 8191 5 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7C01A4257
+20210515042745 2 6 100 8191 5 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7C7338DAF
+20210515064126 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7D05D5BDB
+20210515065958 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7D190DF9B
+20210515070456 2 6 100 8191 5 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7D1DF4F37
+20210515073228 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7D3BDC2E3
+20210515082306 2 6 100 8191 5 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7D7180387
+20210515083006 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7D78B18B3
+20210515090500 2 6 100 8191 5 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7D9CF96DF
+20210515092343 2 6 100 8191 5 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7DB040157
+20210515100730 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7DDEA0AE3
+20210515102122 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7DED3CFBB
+20210515111047 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7E218ED8B
+20210515112711 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7E32683E3
+20210515130646 2 6 100 8191 5 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7E9836B47
+20210515144634 2 6 100 8191 5 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7EFF3474F
+20210515145430 2 6 100 8191 5 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7F06C080F
+20210515151337 2 6 100 8191 5 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7F1A0735F
+20210515155550 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7F4535AFB
+20210515170646 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7F8D31C5B
+20210515182201 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE7FD9B5FC3
+20210515190839 2 6 100 8191 5 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE80086B9E7
+20210515195013 2 6 100 8191 5 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE80312E5FF
+20210515215158 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE80ABDE71B
+20210515222330 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE80CB1A273
+20210515223057 2 6 100 8191 5 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE80D1F22DF
+20210516000343 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE812D0CF63
+20210516001402 2 6 100 8191 5 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE813696F87
+20210516033418 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE81F94FB1B
+20210516034751 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE820609413
+20210516043347 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE8232145B3
+20210516043651 2 6 100 8191 5 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE82348D01F
+20210516052501 2 6 100 8191 5 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE8262E1FE7
+20210516061031 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE828E7F28B
+20210516070338 2 6 100 8191 2 DD4A2D5D7B10514C9CBEB91330C309D38566FF0D418584030168693F4060DE64CC996D4F9D446AEF0F5C78E4BCFD2067A117FF78EDB5E248F494F0F6AAF718220D801EE111F50E6FD20092C3C4CFF0452384E6EF948624A85ACB5A40280F32E0C1824BF0D7215F20DC356DCF39DB382083F4CAB942564DEDA2B38211789A707CA0388E27191F3238E75B8FA352A37BA743CB80351DB5DC8F4F5CFD79C920102A838B5EE973E4F95253B43B0E327F31CBBBD7932E13C2DB0F43CCE1FB609DFE4140CA3B048CFB3C929AB9685EBFFD09F08625727583AE0E4AB61DDE47807E124D84F3FCA43FC92A7AA931FBE193CC609611FC30E873F1988D92251DF49C1E2A9126C63FA3FE19C4D9066FEC94693CBCC0951624C3F410F729F9539D35C848D924C29CF512ED032AA4B5AC4A2440197C81D5EBA6A5A9CBC11F4660FFE7597F60E6AF25944E425D724606ABFCB84878D66CE017D3ED6B07CA4FCA5B5CFA57C82FCCF1172850678F63F6F2277F242C1DACB5D16D2BC5EC611C45751A8AFC3179CEFA82334172D326B3CFCB9FB43B2E981AB6BC4033CC2E7BB57E6A19A74953E1E5E7A2E4463E3C3C950ACC5128D1DC543A6BB34C3AE3F4C33818923C1911329D5BA8D6AF1ED5915E1A1E0824CC612898AF0B0EBB553D5760AD00913D60A5649C860B3FCA1049A55BC24045298537BAA1E47B9C779FF24654889FF6162DFF3DF787E53CE4D1355AAF425B9B7CACE1C9FE076D61BD6A1887155813C7C922ABF8D161B546A94D091365D7EF693532B7CB2352F73EB8E4CB75E5771E21C2691C1AB114880E0AB104869DA6425900EF55A5B95FED252DC1D70B2473B26AEFFBCD5569F895D16B50F030B7EB2846985D185880F2B4624622F28CDD73CAEBBC318187AD69432EF31B38831E67222CCBA64DFBF0937A297E3473421506E7AA1D30DABE3841E8F58D6C6B1D0596867D80ADA9A9ADD06A1FB634DBF7B1FEF67DBABFF52538C4563B90FD343F711822EA17054A9FD1D61B9FD78CD083345E7544853B5D284CC73082C2042BFF6C2614FB1F129F7B7E2C07DFF784DCC5859A8306A33807ED27958C3FFD25F13537F869248BE6E4B3ADD9F03E5DF976D1BCEE46C30B5E79AFCF5233F3E4FE05EE6E5AA17A0E44BD67B1ED69F51F5EF287E531FA51B4FA545BC0C3EFB16D8424518AE27498DFBCBF79D129CA3AF38108C86266527435FC27AFA4201609B974EC1CEF0741BC478676736135E5E2BA6297C061E585CE267A99CB411505FC26A2E54209C94D6757CA9B71127B401DEB364D0A86C4C22A5A65CDD2504C57602959D2DB6E8BAC42720A76B8910D08852AE79D91F195A046D86BC3D88660ECC6BAB9CA26B765B45C6DC2571685EE8F25EEBC7B7FEE5AE00B492CF90CFC2C2348F92D2C0D4776FC611CB1F7064E40230E74302CF83A93F177A53CE82C2463FB
diff --git a/monitor.c b/monitor.c
index b454cc165..677641cb4 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.c,v 1.210 2020/03/13 03:17:07 djm Exp $ */
+/* $OpenBSD: monitor.c,v 1.228 2021/08/11 05:20:17 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -104,7 +104,6 @@ static Gssctxt *gsscontext = NULL;
/* Imports */
extern ServerOptions options;
extern u_int utmp_len;
-extern u_char session_id[];
extern struct sshbuf *loginmsg;
extern struct sshauthopt *auth_opts; /* XXX move to permanent ssh->authctxt? */
@@ -121,8 +120,6 @@ int mm_answer_authserv(struct ssh *, int, struct sshbuf *);
int mm_answer_authpassword(struct ssh *, int, struct sshbuf *);
int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *);
int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *);
-int mm_answer_skeyquery(struct ssh *, int, struct sshbuf *);
-int mm_answer_skeyrespond(struct ssh *, int, struct sshbuf *);
int mm_answer_keyallowed(struct ssh *, int, struct sshbuf *);
int mm_answer_keyverify(struct ssh *, int, struct sshbuf *);
int mm_answer_pty(struct ssh *, int, struct sshbuf *);
@@ -160,7 +157,7 @@ static Authctxt *authctxt;
/* local state for key verify */
static u_char *key_blob = NULL;
static size_t key_bloblen = 0;
-static int key_blobtype = MM_NOKEY;
+static u_int key_blobtype = MM_NOKEY;
static struct sshauthopt *key_opts = NULL;
static char *hostbased_cuser = NULL;
static char *hostbased_chost = NULL;
@@ -309,8 +306,7 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor)
if (authenticated &&
!auth2_update_methods_lists(authctxt,
auth_method, auth_submethod)) {
- debug3("%s: method %s: partial", __func__,
- auth_method);
+ debug3_f("method %s: partial", auth_method);
authenticated = 0;
partial = 1;
}
@@ -318,8 +314,8 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor)
if (authenticated) {
if (!(ent->flags & MON_AUTHDECIDE))
- fatal("%s: unexpected authentication from %d",
- __func__, ent->type);
+ fatal_f("unexpected authentication from %d",
+ ent->type);
if (authctxt->pw->pw_uid == 0 &&
!auth_root_allowed(ssh, auth_method))
authenticated = 0;
@@ -352,12 +348,11 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor)
}
if (!authctxt->valid)
- fatal("%s: authenticated invalid user", __func__);
+ fatal_f("authenticated invalid user");
if (strcmp(auth_method, "unknown") == 0)
- fatal("%s: authentication method name unknown", __func__);
+ fatal_f("authentication method name unknown");
- debug("%s: %s has been authenticated by privileged process",
- __func__, authctxt->user);
+ debug_f("user %s authenticated by privileged process", authctxt->user);
ssh->authctxt = NULL;
ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user);
@@ -420,47 +415,47 @@ static int
monitor_read_log(struct monitor *pmonitor)
{
struct sshbuf *logmsg;
- u_int len, level;
+ u_int len, level, forced;
char *msg;
u_char *p;
int r;
if ((logmsg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
/* Read length */
if ((r = sshbuf_reserve(logmsg, 4, &p)) != 0)
- fatal("%s: reserve: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reserve len");
if (atomicio(read, pmonitor->m_log_recvfd, p, 4) != 4) {
if (errno == EPIPE) {
sshbuf_free(logmsg);
- debug("%s: child log fd closed", __func__);
+ debug_f("child log fd closed");
close(pmonitor->m_log_recvfd);
pmonitor->m_log_recvfd = -1;
return -1;
}
- fatal("%s: log fd read: %s", __func__, strerror(errno));
+ fatal_f("log fd read: %s", strerror(errno));
}
if ((r = sshbuf_get_u32(logmsg, &len)) != 0)
- fatal("%s: get len: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse len");
if (len <= 4 || len > 8192)
- fatal("%s: invalid log message length %u", __func__, len);
+ fatal_f("invalid log message length %u", len);
/* Read severity, message */
sshbuf_reset(logmsg);
if ((r = sshbuf_reserve(logmsg, len, &p)) != 0)
- fatal("%s: reserve: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reserve msg");
if (atomicio(read, pmonitor->m_log_recvfd, p, len) != len)
- fatal("%s: log fd read: %s", __func__, strerror(errno));
+ fatal_f("log fd read: %s", strerror(errno));
if ((r = sshbuf_get_u32(logmsg, &level)) != 0 ||
+ (r = sshbuf_get_u32(logmsg, &forced)) != 0 ||
(r = sshbuf_get_cstring(logmsg, &msg, NULL)) != 0)
- fatal("%s: decode: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
/* Log it */
if (log_level_name(level) == NULL)
- fatal("%s: invalid log level %u (corrupted message?)",
- __func__, level);
- do_log2(level, "%s [preauth]", msg);
+ fatal_f("invalid log level %u (corrupted message?)", level);
+ sshlogdirect(level, forced, "%s [preauth]", msg);
sshbuf_free(logmsg);
free(msg);
@@ -486,7 +481,7 @@ monitor_read(struct ssh *ssh, struct monitor *pmonitor, struct mon_table *ent,
if (poll(pfd, pfd[1].fd == -1 ? 1 : 2, -1) == -1) {
if (errno == EINTR || errno == EAGAIN)
continue;
- fatal("%s: poll: %s", __func__, strerror(errno));
+ fatal_f("poll: %s", strerror(errno));
}
if (pfd[1].revents) {
/*
@@ -501,13 +496,13 @@ monitor_read(struct ssh *ssh, struct monitor *pmonitor, struct mon_table *ent,
}
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
mm_request_receive(pmonitor->m_sendfd, m);
if ((r = sshbuf_get_u8(m, &type)) != 0)
- fatal("%s: decode: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse type");
- debug3("%s: checking request %d", __func__, type);
+ debug3_f("checking request %d", type);
while (ent->f != NULL) {
if (ent->type == type)
@@ -517,15 +512,13 @@ monitor_read(struct ssh *ssh, struct monitor *pmonitor, struct mon_table *ent,
if (ent->f != NULL) {
if (!(ent->flags & MON_PERMIT))
- fatal("%s: unpermitted request %d", __func__,
- type);
+ fatal_f("unpermitted request %d", type);
ret = (*ent->f)(ssh, pmonitor->m_sendfd, m);
sshbuf_free(m);
/* The child may use this request only once, disable it */
if (ent->flags & MON_ONCE) {
- debug2("%s: %d used once, disabling now", __func__,
- type);
+ debug2_f("%d used once, disabling now", type);
ent->flags &= ~MON_PERMIT;
}
@@ -535,7 +528,7 @@ monitor_read(struct ssh *ssh, struct monitor *pmonitor, struct mon_table *ent,
return ret;
}
- fatal("%s: unsupported request: %d", __func__, type);
+ fatal_f("unsupported request: %d", type);
/* NOTREACHED */
return (-1);
@@ -580,21 +573,19 @@ mm_answer_moduli(struct ssh *ssh, int sock, struct sshbuf *m)
if ((r = sshbuf_get_u32(m, &min)) != 0 ||
(r = sshbuf_get_u32(m, &want)) != 0 ||
(r = sshbuf_get_u32(m, &max)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
- debug3("%s: got parameters: %d %d %d",
- __func__, min, want, max);
+ debug3_f("got parameters: %d %d %d", min, want, max);
/* We need to check here, too, in case the child got corrupted */
if (max < min || want < min || max < want)
- fatal("%s: bad parameters: %d %d %d",
- __func__, min, want, max);
+ fatal_f("bad parameters: %d %d %d", min, want, max);
sshbuf_reset(m);
dh = choose_dh(min, want, max);
if (dh == NULL) {
if ((r = sshbuf_put_u8(m, 0)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble empty");
return (0);
} else {
/* Send first bignum */
@@ -602,7 +593,7 @@ mm_answer_moduli(struct ssh *ssh, int sock, struct sshbuf *m)
if ((r = sshbuf_put_u8(m, 1)) != 0 ||
(r = sshbuf_put_bignum2(m, dh_p)) != 0 ||
(r = sshbuf_put_bignum2(m, dh_g)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
DH_free(dh);
}
@@ -624,15 +615,15 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m)
u_int keyid, compat;
const char proof_req[] = "hostkeys-prove-00@openssh.com";
- debug3("%s", __func__);
+ debug3_f("entering");
if ((r = sshbuf_get_u32(m, &keyid)) != 0 ||
(r = sshbuf_get_string(m, &p, &datlen)) != 0 ||
(r = sshbuf_get_cstring(m, &alg, &alglen)) != 0 ||
(r = sshbuf_get_u32(m, &compat)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (keyid > INT_MAX)
- fatal("%s: invalid key ID", __func__);
+ fatal_f("invalid key ID");
/*
* Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes),
@@ -651,21 +642,20 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m)
* the client sent us.
*/
if (session_id2_len == 0) /* hostkeys is never first */
- fatal("%s: bad data length: %zu", __func__, datlen);
+ fatal_f("bad data length: %zu", datlen);
if ((key = get_hostkey_public_by_index(keyid, ssh)) == NULL)
- fatal("%s: no hostkey for index %d", __func__, keyid);
+ fatal_f("no hostkey for index %d", keyid);
if ((sigbuf = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_cstring(sigbuf, proof_req)) != 0 ||
(r = sshbuf_put_string(sigbuf, session_id2,
session_id2_len)) != 0 ||
(r = sshkey_puts(key, sigbuf)) != 0)
- fatal("%s: couldn't prepare private key "
- "proof buffer: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble private key proof");
if (datlen != sshbuf_len(sigbuf) ||
memcmp(p, sshbuf_ptr(sigbuf), sshbuf_len(sigbuf)) != 0)
- fatal("%s: bad data length: %zu, hostkey proof len %zu",
- __func__, datlen, sshbuf_len(sigbuf));
+ fatal_f("bad data length: %zu, hostkey proof len %zu",
+ datlen, sshbuf_len(sigbuf));
sshbuf_free(sigbuf);
is_proof = 1;
}
@@ -679,25 +669,22 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m)
if ((key = get_hostkey_by_index(keyid)) != NULL) {
if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg,
- options.sk_provider, compat)) != 0)
- fatal("%s: sshkey_sign failed: %s",
- __func__, ssh_err(r));
+ options.sk_provider, NULL, compat)) != 0)
+ fatal_fr(r, "sign");
} else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL &&
auth_sock > 0) {
if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen,
- p, datlen, alg, compat)) != 0) {
- fatal("%s: ssh_agent_sign failed: %s",
- __func__, ssh_err(r));
- }
+ p, datlen, alg, compat)) != 0)
+ fatal_fr(r, "agent sign");
} else
- fatal("%s: no hostkey from index %d", __func__, keyid);
+ fatal_f("no hostkey from index %d", keyid);
- debug3("%s: %s signature %p(%zu)", __func__,
- is_proof ? "hostkey proof" : "KEX", signature, siglen);
+ debug3_f("%s %s signature len=%zu", alg,
+ is_proof ? "hostkey proof" : "KEX", siglen);
sshbuf_reset(m);
if ((r = sshbuf_put_string(m, signature, siglen)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
free(alg);
free(p);
@@ -711,8 +698,14 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m)
return (0);
}
-/* Retrieves the password entry and also checks if the user is permitted */
+#define PUTPW(b, id) \
+ do { \
+ if ((r = sshbuf_put_string(b, \
+ &pwent->id, sizeof(pwent->id))) != 0) \
+ fatal_fr(r, "assemble %s", #id); \
+ } while (0)
+/* Retrieves the password entry and also checks if the user is permitted */
int
mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m)
{
@@ -721,13 +714,13 @@ mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m)
int r, allowed = 0;
u_int i;
- debug3("%s", __func__);
+ debug3_f("entering");
if (authctxt->attempt++ != 0)
- fatal("%s: multiple attempts for getpwnam", __func__);
+ fatal_f("multiple attempts for getpwnam");
if ((r = sshbuf_get_cstring(m, &username, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
pwent = getpwnamallow(ssh, username);
@@ -739,7 +732,7 @@ mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m)
if (pwent == NULL) {
if ((r = sshbuf_put_u8(m, 0)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble fakepw");
authctxt->pw = fakepw();
goto out;
}
@@ -748,10 +741,18 @@ mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m)
authctxt->pw = pwent;
authctxt->valid = 1;
- /* XXX don't sent pwent to unpriv; send fake class/dir/shell too */
- if ((r = sshbuf_put_u8(m, 1)) != 0 ||
- (r = sshbuf_put_string(m, pwent, sizeof(*pwent))) != 0 ||
- (r = sshbuf_put_cstring(m, pwent->pw_name)) != 0 ||
+ /* XXX send fake class/dir/shell, etc. */
+ if ((r = sshbuf_put_u8(m, 1)) != 0)
+ fatal_fr(r, "assemble ok");
+ PUTPW(m, pw_uid);
+ PUTPW(m, pw_gid);
+#ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
+ PUTPW(m, pw_change);
+#endif
+#ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
+ PUTPW(m, pw_expire);
+#endif
+ if ((r = sshbuf_put_cstring(m, pwent->pw_name)) != 0 ||
(r = sshbuf_put_cstring(m, "*")) != 0 ||
#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
(r = sshbuf_put_cstring(m, pwent->pw_gecos)) != 0 ||
@@ -761,26 +762,23 @@ mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m)
#endif
(r = sshbuf_put_cstring(m, pwent->pw_dir)) != 0 ||
(r = sshbuf_put_cstring(m, pwent->pw_shell)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble pw");
out:
ssh_packet_set_log_preamble(ssh, "%suser %s",
authctxt->valid ? "authenticating" : "invalid ", authctxt->user);
if ((r = sshbuf_put_string(m, &options, sizeof(options))) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble options");
#define M_CP_STROPT(x) do { \
- if (options.x != NULL) { \
- if ((r = sshbuf_put_cstring(m, options.x)) != 0) \
- fatal("%s: buffer error: %s", \
- __func__, ssh_err(r)); \
- } \
+ if (options.x != NULL && \
+ (r = sshbuf_put_cstring(m, options.x)) != 0) \
+ fatal_fr(r, "assemble %s", #x); \
} while (0)
#define M_CP_STRARRAYOPT(x, nx) do { \
for (i = 0; i < options.nx; i++) { \
if ((r = sshbuf_put_cstring(m, options.x[i])) != 0) \
- fatal("%s: buffer error: %s", \
- __func__, ssh_err(r)); \
+ fatal_fr(r, "assemble %s", #x); \
} \
} while (0)
/* See comment in servconf.h */
@@ -795,10 +793,10 @@ mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m)
* run to it's packet_disconnect(), but it must not allow any
* authentication to succeed.
*/
- debug("%s: no valid authentication method lists", __func__);
+ debug_f("no valid authentication method lists");
}
- debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
+ debug3_f("sending MONITOR_ANS_PWNAM: %d", allowed);
mm_request_send(sock, MONITOR_ANS_PWNAM, m);
/* Allow service/style information on the auth context */
@@ -821,7 +819,7 @@ int mm_answer_auth2_read_banner(struct ssh *ssh, int sock, struct sshbuf *m)
sshbuf_reset(m);
banner = auth2_read_banner();
if ((r = sshbuf_put_cstring(m, banner != NULL ? banner : "")) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
mm_request_send(sock, MONITOR_ANS_AUTH2_READ_BANNER, m);
free(banner);
@@ -837,9 +835,8 @@ mm_answer_authserv(struct ssh *ssh, int sock, struct sshbuf *m)
if ((r = sshbuf_get_cstring(m, &authctxt->service, NULL)) != 0 ||
(r = sshbuf_get_cstring(m, &authctxt->style, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- debug3("%s: service=%s, style=%s",
- __func__, authctxt->service, authctxt->style);
+ fatal_fr(r, "parse");
+ debug3_f("service=%s, style=%s", authctxt->service, authctxt->style);
if (strlen(authctxt->style) == 0) {
free(authctxt->style);
@@ -889,10 +886,10 @@ mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m)
size_t plen = 0;
if (!options.password_authentication)
- fatal("%s: password authentication not enabled", __func__);
+ fatal_f("password authentication not enabled");
#if !defined(ANDROID)
if ((r = sshbuf_get_cstring(m, &passwd, &plen)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
/* Only authenticate if the context is valid */
authenticated = options.password_authentication &&
auth_password(ssh, passwd);
@@ -904,13 +901,14 @@ mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m)
sshbuf_reset(m);
if ((r = sshbuf_put_u32(m, authenticated)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
#ifdef USE_PAM
if ((r = sshbuf_put_u32(m, sshpam_get_maxtries_reached())) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble PAM");
#endif
debug3("%s: sending result %d", __func__, authenticated);
+ debug3_f("sending result %d", authenticated);
mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m);
call_count++;
@@ -933,19 +931,19 @@ mm_answer_bsdauthquery(struct ssh *ssh, int sock, struct sshbuf *m)
int r;
if (!options.kbd_interactive_authentication)
- fatal("%s: kbd-int authentication not enabled", __func__);
+ fatal_f("kbd-int authentication not enabled");
success = bsdauth_query(authctxt, &name, &infotxt, &numprompts,
&prompts, &echo_on) < 0 ? 0 : 1;
sshbuf_reset(m);
if ((r = sshbuf_put_u32(m, success)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
if (success) {
if ((r = sshbuf_put_cstring(m, prompts[0])) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble prompt");
}
- debug3("%s: sending challenge success: %u", __func__, success);
+ debug3_f("sending challenge success: %u", success);
mm_request_send(sock, MONITOR_ANS_BSDAUTHQUERY, m);
if (success) {
@@ -965,23 +963,23 @@ mm_answer_bsdauthrespond(struct ssh *ssh, int sock, struct sshbuf *m)
int r, authok;
if (!options.kbd_interactive_authentication)
- fatal("%s: kbd-int authentication not enabled", __func__);
+ fatal_f("kbd-int authentication not enabled");
if (authctxt->as == NULL)
- fatal("%s: no bsd auth session", __func__);
+ fatal_f("no bsd auth session");
if ((r = sshbuf_get_cstring(m, &response, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- authok = options.challenge_response_authentication &&
+ fatal_fr(r, "parse");
+ authok = options.kbd_interactive_authentication &&
auth_userresponse(authctxt->as, response, 0);
authctxt->as = NULL;
- debug3("%s: <%s> = <%d>", __func__, response, authok);
+ debug3_f("<%s> = <%d>", response, authok);
free(response);
sshbuf_reset(m);
if ((r = sshbuf_put_u32(m, authok)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
- debug3("%s: sending authenticated: %d", __func__, authok);
+ debug3_f("sending authenticated: %d", authok);
mm_request_send(sock, MONITOR_ANS_BSDAUTHRESPOND, m);
auth_method = "keyboard-interactive";
@@ -1160,25 +1158,23 @@ mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m)
struct sshkey *key = NULL;
char *cuser, *chost;
u_int pubkey_auth_attempt;
- enum mm_keytype type = 0;
+ u_int type = 0;
int r, allowed = 0;
struct sshauthopt *opts = NULL;
- debug3("%s entering", __func__);
+ debug3_f("entering");
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_cstring(m, &cuser, NULL)) != 0 ||
(r = sshbuf_get_cstring(m, &chost, NULL)) != 0 ||
(r = sshkey_froms(m, &key)) != 0 ||
(r = sshbuf_get_u32(m, &pubkey_auth_attempt)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
-
- debug3("%s: key_from_blob: %p", __func__, key);
+ fatal_fr(r, "parse");
if (key != NULL && authctxt->valid) {
/* These should not make it past the privsep child */
if (sshkey_type_plain(key->type) == KEY_RSA &&
- (datafellows & SSH_BUG_RSASIGMD5) != 0)
- fatal("%s: passed a SSH_BUG_RSASIGMD5 key", __func__);
+ (ssh->compat & SSH_BUG_RSASIGMD5) != 0)
+ fatal_f("passed a SSH_BUG_RSASIGMD5 key");
switch (type) {
case MM_USERKEY:
@@ -1188,7 +1184,7 @@ mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m)
if (auth2_key_already_used(authctxt, key))
break;
if (!key_base_type_match(auth_method, key,
- options.pubkey_key_types))
+ options.pubkey_accepted_algos))
break;
allowed = user_key_allowed(ssh, authctxt->pw, key,
pubkey_auth_attempt, &opts);
@@ -1200,7 +1196,7 @@ mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m)
if (auth2_key_already_used(authctxt, key))
break;
if (!key_base_type_match(auth_method, key,
- options.hostbased_key_types))
+ options.hostbased_accepted_algos))
break;
allowed = hostbased_key_allowed(ssh, authctxt->pw,
cuser, chost, key);
@@ -1209,13 +1205,13 @@ mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m)
cuser, chost);
break;
default:
- fatal("%s: unknown key type %d", __func__, type);
+ fatal_f("unknown key type %u", type);
break;
}
}
- debug3("%s: %s authentication%s: %s key is %s", __func__,
- auth_method, pubkey_auth_attempt ? "" : " test",
+ debug3_f("%s authentication%s: %s key is %s", auth_method,
+ pubkey_auth_attempt ? "" : " test",
(key == NULL || !authctxt->valid) ? "invalid" : sshkey_type(key),
allowed ? "allowed" : "not allowed");
@@ -1227,7 +1223,7 @@ mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m)
if (allowed) {
/* Save temporarily for comparison in verify */
if ((r = sshkey_to_blob(key, &key_blob, &key_bloblen)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshkey_to_blob");
key_blobtype = type;
key_opts = opts;
hostbased_cuser = cuser;
@@ -1242,9 +1238,9 @@ mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m)
sshbuf_reset(m);
if ((r = sshbuf_put_u32(m, allowed)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
if (opts != NULL && (r = sshauthopt_serialise(opts, m, 1)) != 0)
- fatal("%s: sshauthopt_serialise: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshauthopt_serialise");
mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m);
if (!allowed)
@@ -1254,7 +1250,7 @@ mm_answer_keyallowed(struct ssh *ssh, int sock, struct sshbuf *m)
}
static int
-monitor_valid_userblob(const u_char *data, u_int datalen)
+monitor_valid_userblob(struct ssh *ssh, const u_char *data, u_int datalen)
{
struct sshbuf *b;
const u_char *p;
@@ -1264,9 +1260,9 @@ monitor_valid_userblob(const u_char *data, u_int datalen)
int r, fail = 0;
if ((b = sshbuf_from(data, datalen)) == NULL)
- fatal("%s: sshbuf_from", __func__);
+ fatal_f("sshbuf_from");
- if (datafellows & SSH_OLD_SESSIONID) {
+ if (ssh->compat & SSH_OLD_SESSIONID) {
p = sshbuf_ptr(b);
len = sshbuf_len(b);
if ((session_id2 == NULL) ||
@@ -1274,21 +1270,21 @@ monitor_valid_userblob(const u_char *data, u_int datalen)
(timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
fail++;
if ((r = sshbuf_consume(b, session_id2_len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "consume");
} else {
if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse sessionid");
if ((session_id2 == NULL) ||
(len != session_id2_len) ||
(timingsafe_bcmp(p, session_id2, session_id2_len) != 0))
fail++;
}
if ((r = sshbuf_get_u8(b, &type)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse type");
if (type != SSH2_MSG_USERAUTH_REQUEST)
fail++;
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse userstyle");
xasprintf(&userstyle, "%s%s%s", authctxt->user,
authctxt->style ? ":" : "",
authctxt->style ? authctxt->style : "");
@@ -1301,17 +1297,17 @@ monitor_valid_userblob(const u_char *data, u_int datalen)
free(cp);
if ((r = sshbuf_skip_string(b)) != 0 || /* service */
(r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse method");
if (strcmp("publickey", cp) != 0)
fail++;
free(cp);
if ((r = sshbuf_get_u8(b, &type)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse pktype");
if (type == 0)
fail++;
if ((r = sshbuf_skip_string(b)) != 0 || /* pkalg */
(r = sshbuf_skip_string(b)) != 0) /* pkblob */
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse pk");
if (sshbuf_len(b) != 0)
fail++;
sshbuf_free(b);
@@ -1330,9 +1326,9 @@ monitor_valid_hostbasedblob(const u_char *data, u_int datalen,
u_char type;
if ((b = sshbuf_from(data, datalen)) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse sessionid");
if ((session_id2 == NULL) ||
(len != session_id2_len) ||
@@ -1340,11 +1336,11 @@ monitor_valid_hostbasedblob(const u_char *data, u_int datalen,
fail++;
if ((r = sshbuf_get_u8(b, &type)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse type");
if (type != SSH2_MSG_USERAUTH_REQUEST)
fail++;
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse userstyle");
xasprintf(&userstyle, "%s%s%s", authctxt->user,
authctxt->style ? ":" : "",
authctxt->style ? authctxt->style : "");
@@ -1357,17 +1353,17 @@ monitor_valid_hostbasedblob(const u_char *data, u_int datalen,
free(cp);
if ((r = sshbuf_skip_string(b)) != 0 || /* service */
(r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse method");
if (strcmp(cp, "hostbased") != 0)
fail++;
free(cp);
if ((r = sshbuf_skip_string(b)) != 0 || /* pkalg */
(r = sshbuf_skip_string(b)) != 0) /* pkblob */
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse pk");
/* verify client host, strip trailing dot if necessary */
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse host");
if (((len = strlen(cp)) > 0) && cp[len - 1] == '.')
cp[len - 1] = '\0';
if (strcmp(cp, chost) != 0)
@@ -1376,7 +1372,7 @@ monitor_valid_hostbasedblob(const u_char *data, u_int datalen,
/* verify client user */
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse ruser");
if (strcmp(cp, cuser) != 0)
fail++;
free(cp);
@@ -1394,18 +1390,19 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
const u_char *signature, *data, *blob;
char *sigalg = NULL, *fp = NULL;
size_t signaturelen, datalen, bloblen;
- int r, ret, req_presence = 0, valid_data = 0, encoded_ret;
+ int r, ret, req_presence = 0, req_verify = 0, valid_data = 0;
+ int encoded_ret;
struct sshkey_sig_details *sig_details = NULL;
if ((r = sshbuf_get_string_direct(m, &blob, &bloblen)) != 0 ||
(r = sshbuf_get_string_direct(m, &signature, &signaturelen)) != 0 ||
(r = sshbuf_get_string_direct(m, &data, &datalen)) != 0 ||
(r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (hostbased_cuser == NULL || hostbased_chost == NULL ||
!monitor_allowed_key(blob, bloblen))
- fatal("%s: bad key, not previously allowed", __func__);
+ fatal_f("bad key, not previously allowed");
/* Empty signature algorithm means NULL. */
if (*sigalg == '\0') {
@@ -1415,11 +1412,11 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
/* XXX use sshkey_froms here; need to change key_blob, etc. */
if ((r = sshkey_from_blob(blob, bloblen, &key)) != 0)
- fatal("%s: bad public key blob: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse key");
switch (key_blobtype) {
case MM_USERKEY:
- valid_data = monitor_valid_userblob(data, datalen);
+ valid_data = monitor_valid_userblob(ssh, data, datalen);
auth_method = "publickey";
break;
case MM_HOSTKEY:
@@ -1432,15 +1429,17 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
break;
}
if (!valid_data)
- fatal("%s: bad signature data blob", __func__);
+ fatal_f("bad %s signature data blob",
+ key_blobtype == MM_USERKEY ? "userkey" :
+ (key_blobtype == MM_HOSTKEY ? "hostkey" : "unknown"));
if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL)
- fatal("%s: sshkey_fingerprint failed", __func__);
+ fatal_f("sshkey_fingerprint failed");
ret = sshkey_verify(key, signature, signaturelen, data, datalen,
sigalg, ssh->compat, &sig_details);
- debug3("%s: %s %p signature %s%s%s", __func__, auth_method, key,
+ debug3_f("%s %s signature %s%s%s", auth_method, sshkey_type(key),
(ret == 0) ? "verified" : "unverified",
(ret != 0) ? ": " : "", (ret != 0) ? ssh_err(ret) : "");
@@ -1459,6 +1458,18 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
ssh_remote_port(ssh));
ret = SSH_ERR_SIGNATURE_INVALID;
}
+ req_verify = (options.pubkey_auth_options &
+ PUBKEYAUTH_VERIFY_REQUIRED) || key_opts->require_verify;
+ if (req_verify &&
+ (sig_details->sk_flags & SSH_SK_USER_VERIFICATION_REQD) == 0) {
+ error("public key %s %s signature for %s%s from %.128s "
+ "port %d rejected: user verification requirement "
+ "not met ", sshkey_type(key), fp,
+ authctxt->valid ? "" : "invalid user ",
+ authctxt->user, ssh_remote_ipaddr(ssh),
+ ssh_remote_port(ssh));
+ ret = SSH_ERR_SIGNATURE_INVALID;
+ }
}
auth2_record_key(authctxt, ret == 0, key);
@@ -1472,11 +1483,11 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m)
encoded_ret = (ret != 0);
if ((r = sshbuf_put_u32(m, encoded_ret)) != 0 ||
(r = sshbuf_put_u8(m, sig_details != NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
if (sig_details != NULL) {
if ((r = sshbuf_put_u32(m, sig_details->sk_counter)) != 0 ||
(r = sshbuf_put_u8(m, sig_details->sk_flags)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble sk");
}
sshkey_sig_details_free(sig_details);
mm_request_send(sock, MONITOR_ANS_KEYVERIFY, m);
@@ -1516,9 +1527,9 @@ mm_record_login(struct ssh *ssh, Session *s, struct passwd *pw)
static void
mm_session_close(Session *s)
{
- debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid);
+ debug3_f("session %d pid %ld", s->self, (long)s->pid);
if (s->ttyfd != -1) {
- debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd);
+ debug3_f("tty %s ptyfd %d", s->tty, s->ptyfd);
session_pty_cleanup2(s);
}
session_unused(s->self);
@@ -1531,7 +1542,7 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m)
Session *s;
int r, res, fd0;
- debug3("%s entering", __func__);
+ debug3_f("entering");
sshbuf_reset(m);
s = session_new();
@@ -1547,11 +1558,11 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m)
if ((r = sshbuf_put_u32(m, 1)) != 0 ||
(r = sshbuf_put_cstring(m, s->tty)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
/* We need to trick ttyslot */
if (dup2(s->ttyfd, 0) == -1)
- fatal("%s: dup2", __func__);
+ fatal_f("dup2");
mm_record_login(ssh, s, authctxt->pw);
@@ -1560,28 +1571,28 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m)
/* send messages generated by record_login */
if ((r = sshbuf_put_stringb(m, loginmsg)) != 0)
- fatal("%s: put login message: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble loginmsg");
sshbuf_reset(loginmsg);
mm_request_send(sock, MONITOR_ANS_PTY, m);
if (mm_send_fd(sock, s->ptyfd) == -1 ||
mm_send_fd(sock, s->ttyfd) == -1)
- fatal("%s: send fds failed", __func__);
+ fatal_f("send fds failed");
/* make sure nothing uses fd 0 */
if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) == -1)
- fatal("%s: open(/dev/null): %s", __func__, strerror(errno));
+ fatal_f("open(/dev/null): %s", strerror(errno));
if (fd0 != 0)
- error("%s: fd0 %d != 0", __func__, fd0);
+ error_f("fd0 %d != 0", fd0);
- /* slave is not needed */
+ /* slave side of pty is not needed */
close(s->ttyfd);
s->ttyfd = s->ptyfd;
/* no need to dup() because nobody closes ptyfd */
s->ptymaster = s->ptyfd;
- debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd);
+ debug3_f("tty %s ptyfd %d", s->tty, s->ttyfd);
return (0);
@@ -1589,7 +1600,7 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m)
if (s != NULL)
mm_session_close(s);
if ((r = sshbuf_put_u32(m, 0)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble 0");
mm_request_send(sock, MONITOR_ANS_PTY, m);
return (0);
}
@@ -1601,10 +1612,10 @@ mm_answer_pty_cleanup(struct ssh *ssh, int sock, struct sshbuf *m)
char *tty;
int r;
- debug3("%s entering", __func__);
+ debug3_f("entering");
if ((r = sshbuf_get_cstring(m, &tty, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse tty");
if ((s = session_by_tty(tty)) != NULL)
mm_session_close(s);
sshbuf_reset(m);
@@ -1618,7 +1629,7 @@ mm_answer_term(struct ssh *ssh, int sock, struct sshbuf *req)
extern struct monitor *pmonitor;
int res, status;
- debug3("%s: tearing down sessions", __func__);
+ debug3_f("tearing down sessions");
/* The child is terminating */
session_destroy_all(ssh, &mm_session_close);
@@ -1700,33 +1711,39 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor)
struct kex *kex;
int r;
- debug3("%s: packet_set_state", __func__);
+ debug3_f("packet_set_state");
if ((r = ssh_packet_set_state(ssh, child_state)) != 0)
- fatal("%s: packet_set_state: %s", __func__, ssh_err(r));
+ fatal_fr(r, "packet_set_state");
sshbuf_free(child_state);
child_state = NULL;
-
- if ((kex = ssh->kex) != NULL) {
- /* XXX set callbacks */
+ if ((kex = ssh->kex) == NULL)
+ fatal_f("internal error: ssh->kex == NULL");
+ if (session_id2_len != sshbuf_len(ssh->kex->session_id)) {
+ fatal_f("incorrect session id length %zu (expected %u)",
+ sshbuf_len(ssh->kex->session_id), session_id2_len);
+ }
+ if (memcmp(sshbuf_ptr(ssh->kex->session_id), session_id2,
+ session_id2_len) != 0)
+ fatal_f("session ID mismatch");
+ /* XXX set callbacks */
#ifdef WITH_OPENSSL
- kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server;
- kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server;
- kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server;
- kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server;
- kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server;
- kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
- kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
+ kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server;
+ kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server;
+ kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server;
+ kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server;
+ kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server;
+ kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
+ kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
# ifdef OPENSSL_HAS_ECC
- kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
+ kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
# endif
#endif /* WITH_OPENSSL */
- kex->kex[KEX_C25519_SHA256] = kex_gen_server;
- kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server;
- kex->load_host_public_key=&get_hostkey_public_by_type;
- kex->load_host_private_key=&get_hostkey_private_by_type;
- kex->host_key_index=&get_hostkey_index;
- kex->sign = sshd_hostkey_sign;
- }
+ kex->kex[KEX_C25519_SHA256] = kex_gen_server;
+ kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server;
+ kex->load_host_public_key=&get_hostkey_public_by_type;
+ kex->load_host_private_key=&get_hostkey_private_by_type;
+ kex->host_key_index=&get_hostkey_index;
+ kex->sign = sshd_hostkey_sign;
}
/* This function requires careful sanity checking */
@@ -1734,13 +1751,13 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor)
void
mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor)
{
- debug3("%s: Waiting for new keys", __func__);
+ debug3_f("Waiting for new keys");
if ((child_state = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT,
child_state);
- debug3("%s: GOT new keys", __func__);
+ debug3_f("GOT new keys");
}
@@ -1760,7 +1777,7 @@ monitor_openfds(struct monitor *mon, int do_logfds)
#endif
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
- fatal("%s: socketpair: %s", __func__, strerror(errno));
+ fatal_f("socketpair: %s", strerror(errno));
#ifdef SO_ZEROIZE
if (setsockopt(pair[0], SOL_SOCKET, SO_ZEROIZE, &on, sizeof(on)) == -1)
error("setsockopt SO_ZEROIZE(0): %.100s", strerror(errno));
@@ -1774,7 +1791,7 @@ monitor_openfds(struct monitor *mon, int do_logfds)
if (do_logfds) {
if (pipe(pair) == -1)
- fatal("%s: pipe: %s", __func__, strerror(errno));
+ fatal_f("pipe: %s", strerror(errno));
FD_CLOSEONEXEC(pair[0]);
FD_CLOSEONEXEC(pair[1]);
mon->m_log_recvfd = pair[0];
@@ -1813,10 +1830,10 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m)
int r;
if (!options.gss_authentication)
- fatal("%s: GSSAPI authentication not enabled", __func__);
+ fatal_f("GSSAPI authentication not enabled");
if ((r = sshbuf_get_string(m, &p, &len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
goid.elements = p;
goid.length = len;
@@ -1826,7 +1843,7 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m)
sshbuf_reset(m);
if ((r = sshbuf_put_u32(m, major)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
mm_request_send(sock, MONITOR_ANS_GSSSETUP, m);
@@ -1846,10 +1863,10 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m)
int r;
if (!options.gss_authentication)
- fatal("%s: GSSAPI authentication not enabled", __func__);
+ fatal_f("GSSAPI authentication not enabled");
if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "ssh_gssapi_get_buffer_desc");
major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
free(in.value);
@@ -1857,7 +1874,7 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m)
if ((r = sshbuf_put_u32(m, major)) != 0 ||
(r = sshbuf_put_string(m, out.value, out.length)) != 0 ||
(r = sshbuf_put_u32(m, flags)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
mm_request_send(sock, MONITOR_ANS_GSSSTEP, m);
gss_release_buffer(&minor, &out);
@@ -1878,11 +1895,11 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m)
int r;
if (!options.gss_authentication)
- fatal("%s: GSSAPI authentication not enabled", __func__);
+ fatal_f("GSSAPI authentication not enabled");
if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 ||
(r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "ssh_gssapi_get_buffer_desc");
ret = ssh_gssapi_checkmic(gsscontext, &gssbuf, &mic);
@@ -1891,7 +1908,7 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m)
sshbuf_reset(m);
if ((r = sshbuf_put_u32(m, ret)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
mm_request_send(sock, MONITOR_ANS_GSSCHECKMIC, m);
@@ -1908,15 +1925,15 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m)
const char *displayname;
if (!options.gss_authentication)
- fatal("%s: GSSAPI authentication not enabled", __func__);
+ fatal_f("GSSAPI authentication not enabled");
authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
sshbuf_reset(m);
if ((r = sshbuf_put_u32(m, authenticated)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
- debug3("%s: sending result %d", __func__, authenticated);
+ debug3_f("sending result %d", authenticated);
mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m);
auth_method = "gssapi-with-mic";
diff --git a/monitor_fdpass.c b/monitor_fdpass.c
index d766edcf1..a07727a8e 100644
--- a/monitor_fdpass.c
+++ b/monitor_fdpass.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_fdpass.c,v 1.21 2016/02/29 20:22:36 jca Exp $ */
+/* $OpenBSD: monitor_fdpass.c,v 1.22 2020/10/18 11:32:01 djm Exp $ */
/*
* Copyright 2001 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
@@ -89,17 +89,16 @@ mm_send_fd(int sock, int fd)
pfd.events = POLLOUT;
while ((n = sendmsg(sock, &msg, 0)) == -1 &&
(errno == EAGAIN || errno == EINTR)) {
- debug3("%s: sendmsg(%d): %s", __func__, fd, strerror(errno));
+ debug3_f("sendmsg(%d): %s", fd, strerror(errno));
(void)poll(&pfd, 1, -1);
}
if (n == -1) {
- error("%s: sendmsg(%d): %s", __func__, fd,
- strerror(errno));
+ error_f("sendmsg(%d): %s", fd, strerror(errno));
return -1;
}
if (n != 1) {
- error("%s: sendmsg: expected sent 1 got %zd", __func__, n);
+ error_f("sendmsg: expected sent 1 got %zd", n);
return -1;
}
return 0;
@@ -145,35 +144,34 @@ mm_receive_fd(int sock)
pfd.events = POLLIN;
while ((n = recvmsg(sock, &msg, 0)) == -1 &&
(errno == EAGAIN || errno == EINTR)) {
- debug3("%s: recvmsg: %s", __func__, strerror(errno));
+ debug3_f("recvmsg: %s", strerror(errno));
(void)poll(&pfd, 1, -1);
}
if (n == -1) {
- error("%s: recvmsg: %s", __func__, strerror(errno));
+ error_f("recvmsg: %s", strerror(errno));
return -1;
}
if (n != 1) {
- error("%s: recvmsg: expected received 1 got %zd", __func__, n);
+ error_f("recvmsg: expected received 1 got %zd", n);
return -1;
}
#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
if (msg.msg_accrightslen != sizeof(fd)) {
- error("%s: no fd", __func__);
+ error_f("no fd");
return -1;
}
#else
cmsg = CMSG_FIRSTHDR(&msg);
if (cmsg == NULL) {
- error("%s: no message header", __func__);
+ error_f("no message header");
return -1;
}
#ifndef BROKEN_CMSG_TYPE
if (cmsg->cmsg_type != SCM_RIGHTS) {
- error("%s: expected type %d got %d", __func__,
- SCM_RIGHTS, cmsg->cmsg_type);
+ error_f("expected %d got %d", SCM_RIGHTS, cmsg->cmsg_type);
return -1;
}
#endif
@@ -181,7 +179,7 @@ mm_receive_fd(int sock)
#endif
return fd;
#else
- error("%s: file descriptor passing not supported", __func__);
+ error_f("file descriptor passing not supported");
return -1;
#endif
}
diff --git a/monitor_wrap.c b/monitor_wrap.c
index 001a8fa1c..748333c75 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_wrap.c,v 1.117 2019/12/15 18:57:30 djm Exp $ */
+/* $OpenBSD: monitor_wrap.c,v 1.123 2021/04/15 16:24:31 markus Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -82,7 +82,7 @@ extern struct sshbuf *loginmsg;
extern ServerOptions options;
void
-mm_log_handler(LogLevel level, const char *msg, void *ctx)
+mm_log_handler(LogLevel level, int forced, const char *msg, void *ctx)
{
struct sshbuf *log_msg;
struct monitor *mon = (struct monitor *)ctx;
@@ -90,21 +90,22 @@ mm_log_handler(LogLevel level, const char *msg, void *ctx)
size_t len;
if (mon->m_log_sendfd == -1)
- fatal("%s: no log channel", __func__);
+ fatal_f("no log channel");
if ((log_msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u32(log_msg, 0)) != 0 || /* length; filled below */
(r = sshbuf_put_u32(log_msg, level)) != 0 ||
+ (r = sshbuf_put_u32(log_msg, forced)) != 0 ||
(r = sshbuf_put_cstring(log_msg, msg)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
if ((len = sshbuf_len(log_msg)) < 4 || len > 0xffffffff)
- fatal("%s: bad length %zu", __func__, len);
+ fatal_f("bad length %zu", len);
POKE_U32(sshbuf_mutable_ptr(log_msg), len - 4);
if (atomicio(vwrite, mon->m_log_sendfd,
sshbuf_mutable_ptr(log_msg), len) != len)
- fatal("%s: write: %s", __func__, strerror(errno));
+ fatal_f("write: %s", strerror(errno));
sshbuf_free(log_msg);
}
@@ -124,16 +125,16 @@ mm_request_send(int sock, enum monitor_reqtype type, struct sshbuf *m)
size_t mlen = sshbuf_len(m);
u_char buf[5];
- debug3("%s entering: type %d", __func__, type);
+ debug3_f("entering, type %d", type);
if (mlen >= 0xffffffff)
- fatal("%s: bad length %zu", __func__, mlen);
+ fatal_f("bad length %zu", mlen);
POKE_U32(buf, mlen + 1);
buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */
if (atomicio(vwrite, sock, buf, sizeof(buf)) != sizeof(buf))
- fatal("%s: write: %s", __func__, strerror(errno));
+ fatal_f("write: %s", strerror(errno));
if (atomicio(vwrite, sock, sshbuf_mutable_ptr(m), mlen) != mlen)
- fatal("%s: write: %s", __func__, strerror(errno));
+ fatal_f("write: %s", strerror(errno));
}
void
@@ -143,21 +144,21 @@ mm_request_receive(int sock, struct sshbuf *m)
u_int msg_len;
int r;
- debug3("%s entering", __func__);
+ debug3_f("entering");
if (atomicio(read, sock, buf, sizeof(buf)) != sizeof(buf)) {
if (errno == EPIPE)
cleanup_exit(255);
- fatal("%s: read: %s", __func__, strerror(errno));
+ fatal_f("read: %s", strerror(errno));
}
msg_len = PEEK_U32(buf);
if (msg_len > 256 * 1024)
- fatal("%s: read: bad msg_len %d", __func__, msg_len);
+ fatal_f("read: bad msg_len %d", msg_len);
sshbuf_reset(m);
if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reserve");
if (atomicio(read, sock, p, msg_len) != msg_len)
- fatal("%s: read: %s", __func__, strerror(errno));
+ fatal_f("read: %s", strerror(errno));
}
void
@@ -166,14 +167,13 @@ mm_request_receive_expect(int sock, enum monitor_reqtype type, struct sshbuf *m)
u_char rtype;
int r;
- debug3("%s entering: type %d", __func__, type);
+ debug3_f("entering, type %d", type);
mm_request_receive(sock, m);
if ((r = sshbuf_get_u8(m, &rtype)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (rtype != type)
- fatal("%s: read: rtype %d != type %d", __func__,
- rtype, type);
+ fatal_f("read: rtype %d != type %d", rtype, type);
}
#ifdef WITH_OPENSSL
@@ -186,27 +186,27 @@ mm_choose_dh(int min, int nbits, int max)
struct sshbuf *m;
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u32(m, min)) != 0 ||
(r = sshbuf_put_u32(m, nbits)) != 0 ||
(r = sshbuf_put_u32(m, max)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, m);
- debug3("%s: waiting for MONITOR_ANS_MODULI", __func__);
+ debug3_f("waiting for MONITOR_ANS_MODULI");
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, m);
if ((r = sshbuf_get_u8(m, &success)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse success");
if (success == 0)
- fatal("%s: MONITOR_ANS_MODULI failed", __func__);
+ fatal_f("MONITOR_ANS_MODULI failed");
if ((r = sshbuf_get_bignum2(m, &p)) != 0 ||
(r = sshbuf_get_bignum2(m, &g)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse group");
- debug3("%s: remaining %zu", __func__, sshbuf_len(m));
+ debug3_f("remaining %zu", sshbuf_len(m));
sshbuf_free(m);
return (dh_new_group(g, p));
@@ -216,33 +216,42 @@ mm_choose_dh(int min, int nbits, int max)
int
mm_sshkey_sign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, const char *hostkey_alg,
- const char *sk_provider, u_int compat)
+ const char *sk_provider, const char *sk_pin, u_int compat)
{
struct kex *kex = *pmonitor->m_pkex;
struct sshbuf *m;
u_int ndx = kex->host_key_index(key, 0, ssh);
int r;
- debug3("%s entering", __func__);
+ debug3_f("entering");
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u32(m, ndx)) != 0 ||
(r = sshbuf_put_string(m, data, datalen)) != 0 ||
(r = sshbuf_put_cstring(m, hostkey_alg)) != 0 ||
(r = sshbuf_put_u32(m, compat)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, m);
- debug3("%s: waiting for MONITOR_ANS_SIGN", __func__);
+ debug3_f("waiting for MONITOR_ANS_SIGN");
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, m);
if ((r = sshbuf_get_string(m, sigp, lenp)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
sshbuf_free(m);
return (0);
}
+#define GETPW(b, id) \
+ do { \
+ if ((r = sshbuf_get_string_direct(b, &p, &len)) != 0) \
+ fatal_fr(r, "parse pw %s", #id); \
+ if (len != sizeof(pw->id)) \
+ fatal_fr(r, "bad length for %s", #id); \
+ memcpy(&pw->id, p, len); \
+ } while (0)
+
struct passwd *
mm_getpwnamallow(struct ssh *ssh, const char *username)
{
@@ -255,20 +264,20 @@ mm_getpwnamallow(struct ssh *ssh, const char *username)
u_char ok;
const u_char *p;
- debug3("%s entering", __func__);
+ debug3_f("entering");
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_cstring(m, username)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, m);
- debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__);
+ debug3_f("waiting for MONITOR_ANS_PWNAM");
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, m);
if ((r = sshbuf_get_u8(m, &ok)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse success");
if (ok == 0) {
pw = NULL;
goto out;
@@ -276,12 +285,14 @@ mm_getpwnamallow(struct ssh *ssh, const char *username)
/* XXX don't like passing struct passwd like this */
pw = xcalloc(sizeof(*pw), 1);
- if ((r = sshbuf_get_string_direct(m, &p, &len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (len != sizeof(*pw))
- fatal("%s: struct passwd size mismatch", __func__);
- memcpy(pw, p, sizeof(*pw));
-
+ GETPW(m, pw_uid);
+ GETPW(m, pw_gid);
+#ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
+ GETPW(m, pw_change);
+#endif
+#ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
+ GETPW(m, pw_expire);
+#endif
if ((r = sshbuf_get_cstring(m, &pw->pw_name, NULL)) != 0 ||
(r = sshbuf_get_cstring(m, &pw->pw_passwd, NULL)) != 0 ||
#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
@@ -292,24 +303,21 @@ mm_getpwnamallow(struct ssh *ssh, const char *username)
#endif
(r = sshbuf_get_cstring(m, &pw->pw_dir, NULL)) != 0 ||
(r = sshbuf_get_cstring(m, &pw->pw_shell, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse pw");
out:
/* copy options block as a Match directive may have changed some */
if ((r = sshbuf_get_string_direct(m, &p, &len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse opts");
if (len != sizeof(*newopts))
- fatal("%s: option block size mismatch", __func__);
+ fatal_f("option block size mismatch");
newopts = xcalloc(sizeof(*newopts), 1);
memcpy(newopts, p, sizeof(*newopts));
#define M_CP_STROPT(x) do { \
- if (newopts->x != NULL) { \
- if ((r = sshbuf_get_cstring(m, \
- &newopts->x, NULL)) != 0) \
- fatal("%s: buffer error: %s", \
- __func__, ssh_err(r)); \
- } \
+ if (newopts->x != NULL && \
+ (r = sshbuf_get_cstring(m, &newopts->x, NULL)) != 0) \
+ fatal_fr(r, "parse %s", #x); \
} while (0)
#define M_CP_STRARRAYOPT(x, nx) do { \
newopts->x = newopts->nx == 0 ? \
@@ -317,8 +325,7 @@ out:
for (i = 0; i < newopts->nx; i++) { \
if ((r = sshbuf_get_cstring(m, \
&newopts->x[i], NULL)) != 0) \
- fatal("%s: buffer error: %s", \
- __func__, ssh_err(r)); \
+ fatal_fr(r, "parse %s", #x); \
} \
} while (0)
/* See comment in servconf.h */
@@ -328,6 +335,9 @@ out:
copy_set_server_options(&options, newopts, 1);
log_change_level(options.log_level);
+ log_verbose_reset();
+ for (i = 0; i < options.num_log_verbose; i++)
+ log_verbose_add(options.log_verbose[i]);
process_permitopen(ssh, &options);
free(newopts);
@@ -343,17 +353,17 @@ mm_auth2_read_banner(void)
char *banner;
int r;
- debug3("%s entering", __func__);
+ debug3_f("entering");
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, m);
sshbuf_reset(m);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_AUTH2_READ_BANNER, m);
if ((r = sshbuf_get_cstring(m, &banner, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
sshbuf_free(m);
/* treat empty banner as missing banner */
@@ -372,13 +382,13 @@ mm_inform_authserv(char *service, char *style)
struct sshbuf *m;
int r;
- debug3("%s entering", __func__);
+ debug3_f("entering");
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_cstring(m, service)) != 0 ||
(r = sshbuf_put_cstring(m, style ? style : "")) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, m);
@@ -395,32 +405,31 @@ mm_auth_password(struct ssh *ssh, char *password)
u_int maxtries = 0;
#endif
- debug3("%s entering", __func__);
+ debug3_f("entering");
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_cstring(m, password)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, m);
- debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__);
+ debug3_f("waiting for MONITOR_ANS_AUTHPASSWORD");
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_AUTHPASSWORD, m);
if ((r = sshbuf_get_u32(m, &authenticated)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
#ifdef USE_PAM
if ((r = sshbuf_get_u32(m, &maxtries)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse PAM");
if (maxtries > INT_MAX)
- fatal("%s: bad maxtries %u", __func__, maxtries);
+ fatal_fr(r, "bad maxtries");
sshpam_set_maxtries_reached(maxtries);
#endif
sshbuf_free(m);
- debug3("%s: user %sauthenticated",
- __func__, authenticated ? "" : "not ");
+ debug3_f("user %sauthenticated", authenticated ? "" : "not ");
return (authenticated);
}
@@ -447,33 +456,31 @@ mm_key_allowed(enum mm_keytype type, const char *user, const char *host,
int r, allowed = 0;
struct sshauthopt *opts = NULL;
- debug3("%s entering", __func__);
+ debug3_f("entering");
if (authoptp != NULL)
*authoptp = NULL;
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u32(m, type)) != 0 ||
(r = sshbuf_put_cstring(m, user ? user : "")) != 0 ||
(r = sshbuf_put_cstring(m, host ? host : "")) != 0 ||
(r = sshkey_puts(key, m)) != 0 ||
(r = sshbuf_put_u32(m, pubkey_auth_attempt)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, m);
- debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__);
+ debug3_f("waiting for MONITOR_ANS_KEYALLOWED");
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_KEYALLOWED, m);
if ((r = sshbuf_get_u32(m, &allowed)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if (allowed && type == MM_USERKEY) {
- if ((r = sshauthopt_deserialise(m, &opts)) != 0)
- fatal("%s: sshauthopt_deserialise: %s",
- __func__, ssh_err(r));
- }
+ fatal_fr(r, "parse");
+ if (allowed && type == MM_USERKEY &&
+ (r = sshauthopt_deserialise(m, &opts)) != 0)
+ fatal_fr(r, "sshauthopt_deserialise");
sshbuf_free(m);
if (authoptp != NULL) {
@@ -502,31 +509,31 @@ mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen,
u_char sig_details_present, flags;
u_int counter;
- debug3("%s entering", __func__);
+ debug3_f("entering");
if (sig_detailsp != NULL)
*sig_detailsp = NULL;
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshkey_puts(key, m)) != 0 ||
(r = sshbuf_put_string(m, sig, siglen)) != 0 ||
(r = sshbuf_put_string(m, data, datalen)) != 0 ||
(r = sshbuf_put_cstring(m, sigalg == NULL ? "" : sigalg)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, m);
- debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__);
+ debug3_f("waiting for MONITOR_ANS_KEYVERIFY");
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_KEYVERIFY, m);
if ((r = sshbuf_get_u32(m, &encoded_ret)) != 0 ||
(r = sshbuf_get_u8(m, &sig_details_present)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (sig_details_present && encoded_ret == 0) {
if ((r = sshbuf_get_u32(m, &counter)) != 0 ||
(r = sshbuf_get_u8(m, &flags)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse sig_details");
if (sig_detailsp != NULL) {
*sig_detailsp = xcalloc(1, sizeof(**sig_detailsp));
(*sig_detailsp)->sk_counter = counter;
@@ -548,12 +555,11 @@ mm_send_keystate(struct ssh *ssh, struct monitor *monitor)
int r;
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = ssh_packet_get_state(ssh, m)) != 0)
- fatal("%s: get_state failed: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "ssh_packet_get_state");
mm_request_send(monitor->m_recvfd, MONITOR_REQ_KEYEXPORT, m);
- debug3("%s: Finished sending state", __func__);
+ debug3_f("Finished sending state");
sshbuf_free(m);
}
@@ -567,7 +573,7 @@ mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
/* Kludge: ensure there are fds free to receive the pty/tty */
if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
(tmp2 = dup(pmonitor->m_recvfd)) == -1) {
- error("%s: cannot allocate fds for pty", __func__);
+ error_f("cannot allocate fds for pty");
if (tmp1 > 0)
close(tmp1);
if (tmp2 > 0)
@@ -578,34 +584,34 @@ mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
close(tmp2);
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, m);
- debug3("%s: waiting for MONITOR_ANS_PTY", __func__);
+ debug3_f("waiting for MONITOR_ANS_PTY");
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, m);
if ((r = sshbuf_get_u32(m, &success)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse success");
if (success == 0) {
- debug3("%s: pty alloc failed", __func__);
+ debug3_f("pty alloc failed");
sshbuf_free(m);
return (0);
}
if ((r = sshbuf_get_cstring(m, &p, NULL)) != 0 ||
(r = sshbuf_get_cstring(m, &msg, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
sshbuf_free(m);
strlcpy(namebuf, p, namebuflen); /* Possible truncation */
free(p);
if ((r = sshbuf_put(loginmsg, msg, strlen(msg))) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "put loginmsg");
free(msg);
if ((*ptyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1 ||
(*ttyfd = mm_receive_fd(pmonitor->m_recvfd)) == -1)
- fatal("%s: receive fds failed", __func__);
+ fatal_f("receive fds failed");
/* Success */
return (1);
@@ -620,9 +626,9 @@ mm_session_pty_cleanup2(Session *s)
if (s->ttyfd == -1)
return;
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_cstring(m, s->tty)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assmble");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, m);
sshbuf_free(m);
@@ -795,7 +801,7 @@ mm_terminate(void)
struct sshbuf *m;
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, m);
sshbuf_free(m);
}
@@ -821,31 +827,31 @@ mm_bsdauth_query(void *ctx, char **name, char **infotxt,
char *challenge;
int r;
- debug3("%s: entering", __func__);
+ debug3_f("entering");
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, m);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_BSDAUTHQUERY, m);
if ((r = sshbuf_get_u32(m, &success)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse success");
if (success == 0) {
- debug3("%s: no challenge", __func__);
+ debug3_f("no challenge");
sshbuf_free(m);
return (-1);
}
/* Get the challenge, and format the response */
if ((r = sshbuf_get_cstring(m, &challenge, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse challenge");
sshbuf_free(m);
mm_chall_setup(name, infotxt, numprompts, prompts, echo_on);
(*prompts)[0] = challenge;
- debug3("%s: received challenge: %s", __func__, challenge);
+ debug3_f("received challenge: %s", challenge);
return (0);
}
@@ -856,21 +862,21 @@ mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses)
struct sshbuf *m;
int r, authok;
- debug3("%s: entering", __func__);
+ debug3_f("entering");
if (numresponses != 1)
return (-1);
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_cstring(m, responses[0])) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, m);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_BSDAUTHRESPOND, m);
if ((r = sshbuf_get_u32(m, &authok)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
sshbuf_free(m);
return ((authok == 0) ? -1 : 0);
@@ -924,15 +930,15 @@ mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID goid)
*ctx = NULL;
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_string(m, goid->elements, goid->length)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, m);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, m);
if ((r = sshbuf_get_u32(m, &major)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
sshbuf_free(m);
return (major);
@@ -948,19 +954,19 @@ mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in,
int r;
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_string(m, in->value, in->length)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, m);
mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, m);
if ((r = sshbuf_get_u32(m, &major)) != 0 ||
(r = ssh_gssapi_get_buffer_desc(m, out)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (flagsp != NULL) {
if ((r = sshbuf_get_u32(m, &flags)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse flags");
*flagsp = flags;
}
@@ -977,17 +983,17 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
int r;
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_string(m, gssbuf->value, gssbuf->length)) != 0 ||
(r = sshbuf_put_string(m, gssmic->value, gssmic->length)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSCHECKMIC, m);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_GSSCHECKMIC, m);
if ((r = sshbuf_get_u32(m, &major)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
sshbuf_free(m);
return(major);
}
@@ -999,17 +1005,17 @@ mm_ssh_gssapi_userok(char *user)
int r, authenticated = 0;
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_GSSUSEROK, m);
if ((r = sshbuf_get_u32(m, &authenticated)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
sshbuf_free(m);
- debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
+ debug3_f("user %sauthenticated", authenticated ? "" : "not ");
return (authenticated);
}
#endif /* GSSAPI */
diff --git a/monitor_wrap.h b/monitor_wrap.h
index 23ab096aa..a163b67d2 100644
--- a/monitor_wrap.h
+++ b/monitor_wrap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_wrap.h,v 1.44 2019/11/25 00:51:37 djm Exp $ */
+/* $OpenBSD: monitor_wrap.h,v 1.47 2021/04/15 16:24:31 markus Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@@ -40,13 +40,14 @@ struct sshkey;
struct sshauthopt;
struct sshkey_sig_details;
-void mm_log_handler(LogLevel, const char *, void *);
+void mm_log_handler(LogLevel, int, const char *, void *);
int mm_is_monitor(void);
#ifdef WITH_OPENSSL
DH *mm_choose_dh(int, int, int);
#endif
int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *,
- const u_char *, size_t, const char *, const char *, u_int compat);
+ const u_char *, size_t, const char *, const char *,
+ const char *, u_int compat);
void mm_inform_authserv(char *, char *);
struct passwd *mm_getpwnamallow(struct ssh *, const char *);
char *mm_auth2_read_banner(void);
diff --git a/msg.c b/msg.c
index 99c25cd25..d22c4e477 100644
--- a/msg.c
+++ b/msg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: msg.c,v 1.18 2020/01/22 04:49:16 djm Exp $ */
+/* $OpenBSD: msg.c,v 1.20 2020/10/18 11:32:01 djm Exp $ */
/*
* Copyright (c) 2002 Markus Friedl. All rights reserved.
*
@@ -47,16 +47,16 @@ ssh_msg_send(int fd, u_char type, struct sshbuf *m)
u_char buf[5];
u_int mlen = sshbuf_len(m);
- debug3("%s: type %u", __func__, (unsigned int)type & 0xff);
+ debug3_f("type %u", (unsigned int)type & 0xff);
put_u32(buf, mlen + 1);
buf[4] = type; /* 1st byte of payload is mesg-type */
if (atomicio(vwrite, fd, buf, sizeof(buf)) != sizeof(buf)) {
- error("%s: write: %s", __func__, strerror(errno));
+ error_f("write: %s", strerror(errno));
return (-1);
}
if (atomicio(vwrite, fd, sshbuf_mutable_ptr(m), mlen) != mlen) {
- error("%s: write: %s", __func__, strerror(errno));
+ error_f("write: %s", strerror(errno));
return (-1);
}
return (0);
@@ -73,21 +73,21 @@ ssh_msg_recv(int fd, struct sshbuf *m)
if (atomicio(read, fd, buf, sizeof(buf)) != sizeof(buf)) {
if (errno != EPIPE)
- error("%s: read header: %s", __func__, strerror(errno));
+ error_f("read header: %s", strerror(errno));
return (-1);
}
msg_len = get_u32(buf);
- if (msg_len > 256 * 1024) {
- error("%s: read: bad msg_len %u", __func__, msg_len);
+ if (msg_len > sshbuf_max_size(m)) {
+ error_f("read: bad msg_len %u", msg_len);
return (-1);
}
sshbuf_reset(m);
if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) {
- error("%s: buffer error: %s", __func__, ssh_err(r));
+ error_fr(r, "reserve");
return -1;
}
if (atomicio(read, fd, p, msg_len) != msg_len) {
- error("%s: read: %s", __func__, strerror(errno));
+ error_f("read: %s", strerror(errno));
return (-1);
}
return (0);
diff --git a/mux.c b/mux.c
index fb31ad448..4c0eb4249 100644
--- a/mux.c
+++ b/mux.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mux.c,v 1.82 2020/04/30 17:12:20 markus Exp $ */
+/* $OpenBSD: mux.c,v 1.91 2021/07/23 04:00:59 djm Exp $ */
/*
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
*
@@ -71,9 +71,7 @@
/* from ssh.c */
extern int tty_flag;
extern Options options;
-extern int stdin_null_flag;
extern char *host;
-extern int subsystem_flag;
extern struct sshbuf *command;
extern volatile sig_atomic_t quit_pending;
@@ -187,20 +185,20 @@ static const struct {
{ 0, NULL }
};
-/* Cleanup callback fired on closure of mux slave _session_ channel */
+/* Cleanup callback fired on closure of mux client _session_ channel */
/* ARGSUSED */
static void
mux_master_session_cleanup_cb(struct ssh *ssh, int cid, void *unused)
{
Channel *cc, *c = channel_by_id(ssh, cid);
- debug3("%s: entering for channel %d", __func__, cid);
+ debug3_f("entering for channel %d", cid);
if (c == NULL)
- fatal("%s: channel_by_id(%i) == NULL", __func__, cid);
+ fatal_f("channel_by_id(%i) == NULL", cid);
if (c->ctl_chan != -1) {
if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL)
- fatal("%s: channel %d missing control channel %d",
- __func__, c->self, c->ctl_chan);
+ fatal_f("channel %d missing control channel %d",
+ c->self, c->ctl_chan);
c->ctl_chan = -1;
cc->remote_id = 0;
cc->have_remote_id = 0;
@@ -209,26 +207,26 @@ mux_master_session_cleanup_cb(struct ssh *ssh, int cid, void *unused)
channel_cancel_cleanup(ssh, c->self);
}
-/* Cleanup callback fired on closure of mux slave _control_ channel */
+/* Cleanup callback fired on closure of mux client _control_ channel */
/* ARGSUSED */
static void
mux_master_control_cleanup_cb(struct ssh *ssh, int cid, void *unused)
{
Channel *sc, *c = channel_by_id(ssh, cid);
- debug3("%s: entering for channel %d", __func__, cid);
+ debug3_f("entering for channel %d", cid);
if (c == NULL)
- fatal("%s: channel_by_id(%i) == NULL", __func__, cid);
+ fatal_f("channel_by_id(%i) == NULL", cid);
if (c->have_remote_id) {
if ((sc = channel_by_id(ssh, c->remote_id)) == NULL)
- fatal("%s: channel %d missing session channel %u",
- __func__, c->self, c->remote_id);
+ fatal_f("channel %d missing session channel %u",
+ c->self, c->remote_id);
c->remote_id = 0;
c->have_remote_id = 0;
sc->ctl_chan = -1;
if (sc->type != SSH_CHANNEL_OPEN &&
sc->type != SSH_CHANNEL_OPENING) {
- debug2("%s: channel %d: not open", __func__, sc->self);
+ debug2_f("channel %d: not open", sc->self);
chan_mark_dead(ssh, sc);
} else {
if (sc->istate == CHAN_INPUT_OPEN)
@@ -251,7 +249,7 @@ env_permitted(char *env)
return 0;
ret = snprintf(name, sizeof(name), "%.*s", (int)(cp - env), env);
if (ret <= 0 || (size_t)ret >= sizeof(name)) {
- error("%s: name '%.100s...' too long", __func__, env);
+ error_f("name '%.100s...' too long", env);
return 0;
}
@@ -273,21 +271,21 @@ mux_master_process_hello(struct ssh *ssh, u_int rid,
int r;
if (state == NULL)
- fatal("%s: channel %d: c->mux_ctx == NULL", __func__, c->self);
+ fatal_f("channel %d: c->mux_ctx == NULL", c->self);
if (state->hello_rcvd) {
- error("%s: HELLO received twice", __func__);
+ error_f("HELLO received twice");
return -1;
}
if ((r = sshbuf_get_u32(m, &ver)) != 0) {
- error("%s: malformed message: %s", __func__, ssh_err(r));
+ error_fr(r, "parse");
return -1;
}
if (ver != SSHMUX_VER) {
- error("%s: unsupported multiplexing protocol version %u "
- "(expected %u)", __func__, ver, SSHMUX_VER);
+ error_f("unsupported multiplexing protocol version %u "
+ "(expected %u)", ver, SSHMUX_VER);
return -1;
}
- debug2("%s: channel %d slave version %u", __func__, c->self, ver);
+ debug2_f("channel %d client version %u", c->self, ver);
/* No extensions are presently defined */
while (sshbuf_len(m) > 0) {
@@ -296,12 +294,11 @@ mux_master_process_hello(struct ssh *ssh, u_int rid,
if ((r = sshbuf_get_cstring(m, &name, NULL)) != 0 ||
(r = sshbuf_get_string_direct(m, NULL, &value_len)) != 0) {
- error("%s: malformed extension: %s",
- __func__, ssh_err(r));
+ error_fr(r, "parse extension");
return -1;
}
- debug2("%s: Unrecognised extension \"%s\" length %zu",
- __func__, name, value_len);
+ debug2_f("Unrecognised extension \"%s\" length %zu",
+ name, value_len);
free(name);
}
state->hello_rcvd = 1;
@@ -316,7 +313,7 @@ reply_ok(struct sshbuf *reply, u_int rid)
if ((r = sshbuf_put_u32(reply, MUX_S_OK)) != 0 ||
(r = sshbuf_put_u32(reply, rid)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
}
/* Enqueue an error response to the reply buffer */
@@ -328,7 +325,7 @@ reply_error(struct sshbuf *reply, u_int type, u_int rid, const char *msg)
if ((r = sshbuf_put_u32(reply, type)) != 0 ||
(r = sshbuf_put_u32(reply, rid)) != 0 ||
(r = sshbuf_put_cstring(reply, msg)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
}
static int
@@ -363,7 +360,7 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid,
free(cctx->env);
free(cctx->term);
free(cctx);
- error("%s: malformed message", __func__);
+ error_f("malformed message");
return -1;
}
@@ -380,29 +377,28 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid,
cctx->env[env_len++] = cp;
cctx->env[env_len] = NULL;
if (env_len > MUX_MAX_ENV_VARS) {
- error("%s: >%d environment variables received, "
- "ignoring additional", __func__, MUX_MAX_ENV_VARS);
+ error_f(">%d environment variables received, "
+ "ignoring additional", MUX_MAX_ENV_VARS);
break;
}
}
- debug2("%s: channel %d: request tty %d, X %d, agent %d, subsys %d, "
- "term \"%s\", cmd \"%s\", env %u", __func__, c->self,
+ debug2_f("channel %d: request tty %d, X %d, agent %d, subsys %d, "
+ "term \"%s\", cmd \"%s\", env %u", c->self,
cctx->want_tty, cctx->want_x_fwd, cctx->want_agent_fwd,
cctx->want_subsys, cctx->term, cmd, env_len);
if ((cctx->cmd = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put(cctx->cmd, cmd, strlen(cmd))) != 0)
- fatal("%s: sshbuf_put: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_put");
free(cmd);
cmd = NULL;
/* Gather fds from client */
for(i = 0; i < 3; i++) {
if ((new_fd[i] = mm_receive_fd(c->sock)) == -1) {
- error("%s: failed to receive fd %d from slave",
- __func__, i);
+ error_f("failed to receive fd %d from client", i);
for (j = 0; j < i; j++)
close(new_fd[j]);
for (j = 0; j < env_len; j++)
@@ -417,12 +413,12 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid,
}
}
- debug3("%s: got fds stdin %d, stdout %d, stderr %d", __func__,
+ debug3_f("got fds stdin %d, stdout %d, stderr %d",
new_fd[0], new_fd[1], new_fd[2]);
/* XXX support multiple child sessions in future */
if (c->have_remote_id) {
- debug2("%s: session already open", __func__);
+ debug2_f("session already open");
reply_error(reply, MUX_S_FAILURE, rid,
"Multiple sessions not supported");
cleanup:
@@ -443,7 +439,7 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid,
if (options.control_master == SSHCTL_MASTER_ASK ||
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
if (!ask_permission("Allow shared connection to %s? ", host)) {
- debug2("%s: session refused by user", __func__);
+ debug2_f("session refused by user");
reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
"Permission denied");
goto cleanup;
@@ -452,15 +448,7 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid,
/* Try to pick up ttymodes from client before it goes raw */
if (cctx->want_tty && tcgetattr(new_fd[0], &cctx->tio) == -1)
- error("%s: tcgetattr: %s", __func__, strerror(errno));
-
- /* enable nonblocking unless tty */
- if (!isatty(new_fd[0]))
- set_nonblock(new_fd[0]);
- if (!isatty(new_fd[1]))
- set_nonblock(new_fd[1]);
- if (!isatty(new_fd[2]))
- set_nonblock(new_fd[2]);
+ error_f("tcgetattr: %s", strerror(errno));
window = CHAN_SES_WINDOW_DEFAULT;
packetmax = CHAN_SES_PACKET_DEFAULT;
@@ -471,10 +459,10 @@ 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", /*nonblock*/0);
+ CHAN_EXTENDED_WRITE, "client-session", CHANNEL_NONBLOCK_STDIO);
nc->ctl_chan = c->self; /* link session -> control channel */
- c->remote_id = nc->self; /* link control -> session channel */
+ c->remote_id = nc->self; /* link control -> session channel */
c->have_remote_id = 1;
if (cctx->want_tty && escape_char != 0xffffffff) {
@@ -484,8 +472,8 @@ mux_master_process_new_session(struct ssh *ssh, u_int rid,
client_new_escape_filter_ctx((int)escape_char));
}
- debug2("%s: channel_new: %d linked to control channel %d",
- __func__, nc->self, nc->ctl_chan);
+ debug2_f("channel_new: %d linked to control channel %d",
+ nc->self, nc->ctl_chan);
channel_send_open(ssh, nc->self);
channel_register_open_confirm(ssh, nc->self, mux_session_confirm, cctx);
@@ -503,13 +491,13 @@ mux_master_process_alive_check(struct ssh *ssh, u_int rid,
{
int r;
- debug2("%s: channel %d: alive check", __func__, c->self);
+ debug2_f("channel %d: alive check", c->self);
/* prepare reply */
if ((r = sshbuf_put_u32(reply, MUX_S_ALIVE)) != 0 ||
(r = sshbuf_put_u32(reply, rid)) != 0 ||
(r = sshbuf_put_u32(reply, (u_int)getpid())) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
return 0;
}
@@ -518,13 +506,13 @@ static int
mux_master_process_terminate(struct ssh *ssh, u_int rid,
Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
- debug2("%s: channel %d: terminate request", __func__, c->self);
+ debug2_f("channel %d: terminate request", c->self);
if (options.control_master == SSHCTL_MASTER_ASK ||
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
if (!ask_permission("Terminate shared connection to %s? ",
host)) {
- debug2("%s: termination refused by user", __func__);
+ debug2_f("termination refused by user");
reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
"Permission denied");
return 0;
@@ -556,7 +544,7 @@ format_forward(u_int ftype, struct Forward *fwd)
xasprintf(&ret, "dynamic forward %.200s:%d -> *",
(fwd->listen_host == NULL) ?
(options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
- fwd->listen_host, fwd->listen_port);
+ fwd->listen_host, fwd->listen_port);
break;
case MUX_FWD_REMOTE:
xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d",
@@ -568,7 +556,7 @@ format_forward(u_int ftype, struct Forward *fwd)
fwd->connect_host, fwd->connect_port);
break;
default:
- fatal("%s: unknown forward type %u", __func__, ftype);
+ fatal_f("unknown forward type %u", ftype);
}
return ret;
}
@@ -615,11 +603,11 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
if ((c = channel_by_id(ssh, fctx->cid)) == NULL) {
/* no channel for reply */
- error("%s: unknown channel", __func__);
+ error_f("unknown channel");
return;
}
if ((out = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if (fctx->fid >= options.num_remote_forwards ||
(options.remote_forwards[fctx->fid].connect_path == NULL &&
options.remote_forwards[fctx->fid].connect_host == NULL)) {
@@ -627,15 +615,14 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
goto fail;
}
rfwd = &options.remote_forwards[fctx->fid];
- debug("%s: %s for: listen %d, connect %s:%d", __func__,
+ debug_f("%s for: listen %d, connect %s:%d",
type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path :
rfwd->connect_host, rfwd->connect_port);
if (type == SSH2_MSG_REQUEST_SUCCESS) {
if (rfwd->listen_port == 0) {
if ((r = sshpkt_get_u32(ssh, &port)) != 0)
- fatal("%s: packet error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "parse port");
if (port > 65535) {
fatal("Invalid allocated port %u for "
"mux remote forward to %s:%d", port,
@@ -650,9 +637,9 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
(r = sshbuf_put_u32(out, fctx->rid)) != 0 ||
(r = sshbuf_put_u32(out,
rfwd->allocated_port)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
channel_update_permission(ssh, rfwd->handle,
- rfwd->allocated_port);
+ rfwd->allocated_port);
} else {
reply_ok(out, fctx->rid);
}
@@ -667,8 +654,8 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
xasprintf(&failmsg, "remote port forwarding failed for "
"listen port %d", rfwd->listen_port);
- debug2("%s: clearing registered forwarding for listen %d, "
- "connect %s:%d", __func__, rfwd->listen_port,
+ debug2_f("clearing registered forwarding for listen %d, "
+ "connect %s:%d", rfwd->listen_port,
rfwd->connect_path ? rfwd->connect_path :
rfwd->connect_host, rfwd->connect_port);
@@ -679,15 +666,15 @@ mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
memset(rfwd, 0, sizeof(*rfwd));
}
fail:
- error("%s: %s", __func__, failmsg);
+ error_f("%s", failmsg);
reply_error(out, MUX_S_FAILURE, fctx->rid, failmsg);
free(failmsg);
out:
if ((r = sshbuf_put_stringb(c->output, out)) != 0)
- fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r));
+ fatal_fr(r, "enqueue");
sshbuf_free(out);
if (c->mux_pause <= 0)
- fatal("%s: mux_pause %d", __func__, c->mux_pause);
+ fatal_f("mux_pause %d", c->mux_pause);
c->mux_pause = 0; /* start processing messages again */
}
@@ -712,7 +699,7 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid,
(r = sshbuf_get_u32(m, &cport)) != 0 ||
(lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
(cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
- error("%s: malformed message", __func__);
+ error_f("malformed message");
ret = -1;
goto out;
}
@@ -737,12 +724,12 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid,
else
fwd.connect_host = connect_addr;
- debug2("%s: channel %d: request %s", __func__, c->self,
+ debug2_f("channel %d: request %s", c->self,
(fwd_desc = format_forward(ftype, &fwd)));
if (ftype != MUX_FWD_LOCAL && ftype != MUX_FWD_REMOTE &&
ftype != MUX_FWD_DYNAMIC) {
- logit("%s: invalid forwarding type %u", __func__, ftype);
+ logit_f("invalid forwarding type %u", ftype);
invalid:
free(listen_addr);
free(connect_addr);
@@ -751,26 +738,25 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid,
return 0;
}
if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) {
- logit("%s: streamlocal and dynamic forwards "
- "are mutually exclusive", __func__);
+ logit_f("streamlocal and dynamic forwards "
+ "are mutually exclusive");
goto invalid;
}
if (fwd.listen_port != PORT_STREAMLOCAL && fwd.listen_port >= 65536) {
- logit("%s: invalid listen port %u", __func__,
- fwd.listen_port);
+ logit_f("invalid listen port %u", fwd.listen_port);
goto invalid;
}
if ((fwd.connect_port != PORT_STREAMLOCAL &&
fwd.connect_port >= 65536) ||
(ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE &&
fwd.connect_port == 0)) {
- logit("%s: invalid connect port %u", __func__,
+ logit_f("invalid connect port %u",
fwd.connect_port);
goto invalid;
}
if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL &&
fwd.connect_path == NULL) {
- logit("%s: missing connect host", __func__);
+ logit_f("missing connect host");
goto invalid;
}
@@ -782,8 +768,7 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid,
if (compare_forward(&fwd,
options.local_forwards + i)) {
exists:
- debug2("%s: found existing forwarding",
- __func__);
+ debug2_f("found existing forwarding");
reply_ok(reply, rid);
goto out;
}
@@ -795,13 +780,13 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid,
continue;
if (fwd.listen_port != 0)
goto exists;
- debug2("%s: found allocated port", __func__);
+ debug2_f("found allocated port");
if ((r = sshbuf_put_u32(reply,
MUX_S_REMOTE_PORT)) != 0 ||
(r = sshbuf_put_u32(reply, rid)) != 0 ||
(r = sshbuf_put_u32(reply,
options.remote_forwards[i].allocated_port)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply FWD_REMOTE");
goto out;
}
break;
@@ -810,7 +795,7 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid,
if (options.control_master == SSHCTL_MASTER_ASK ||
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
if (!ask_permission("Open %s on %s?", fwd_desc, host)) {
- debug2("%s: forwarding refused by user", __func__);
+ debug2_f("forwarding refused by user");
reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
"Permission denied");
goto out;
@@ -821,7 +806,7 @@ mux_master_process_open_fwd(struct ssh *ssh, u_int rid,
if (!channel_setup_local_fwd_listener(ssh, &fwd,
&options.fwd_opts)) {
fail:
- logit("%s: requested %s failed", __func__, fwd_desc);
+ logit_f("requested %s failed", fwd_desc);
reply_error(reply, MUX_S_FAILURE, rid,
"Port forwarding failed");
goto out;
@@ -879,7 +864,7 @@ mux_master_process_close_fwd(struct ssh *ssh, u_int rid,
(r = sshbuf_get_u32(m, &cport)) != 0 ||
(lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
(cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
- error("%s: malformed message", __func__);
+ error_f("malformed message");
ret = -1;
goto out;
}
@@ -905,7 +890,7 @@ mux_master_process_close_fwd(struct ssh *ssh, u_int rid,
else
fwd.connect_host = connect_addr;
- debug2("%s: channel %d: request cancel %s", __func__, c->self,
+ debug2_f("channel %d: request cancel %s", c->self,
(fwd_desc = format_forward(ftype, &fwd)));
/* make sure this has been requested */
@@ -984,18 +969,16 @@ mux_master_process_stdio_fwd(struct ssh *ssh, u_int rid,
(r = sshbuf_get_cstring(m, &chost, NULL)) != 0 ||
(r = sshbuf_get_u32(m, &cport)) != 0) {
free(chost);
- error("%s: malformed message", __func__);
+ error_f("malformed message");
return -1;
}
- debug2("%s: channel %d: request stdio fwd to %s:%u",
- __func__, c->self, chost, cport);
+ debug2_f("channel %d: stdio fwd to %s:%u", c->self, chost, cport);
/* Gather fds from client */
for(i = 0; i < 2; i++) {
if ((new_fd[i] = mm_receive_fd(c->sock)) == -1) {
- error("%s: failed to receive fd %d from slave",
- __func__, i);
+ error_f("failed to receive fd %d from client", i);
for (j = 0; j < i; j++)
close(new_fd[j]);
free(chost);
@@ -1007,12 +990,11 @@ mux_master_process_stdio_fwd(struct ssh *ssh, u_int rid,
}
}
- debug3("%s: got fds stdin %d, stdout %d", __func__,
- new_fd[0], new_fd[1]);
+ debug3_f("got fds stdin %d, stdout %d", new_fd[0], new_fd[1]);
/* XXX support multiple child sessions in future */
if (c->have_remote_id) {
- debug2("%s: session already open", __func__);
+ debug2_f("session already open");
reply_error(reply, MUX_S_FAILURE, rid,
"Multiple sessions not supported");
cleanup:
@@ -1026,28 +1008,22 @@ mux_master_process_stdio_fwd(struct ssh *ssh, u_int rid,
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
if (!ask_permission("Allow forward to %s:%u? ",
chost, cport)) {
- debug2("%s: stdio fwd refused by user", __func__);
+ debug2_f("stdio fwd refused by user");
reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
"Permission denied");
goto cleanup;
}
}
- /* enable nonblocking unless tty */
- if (!isatty(new_fd[0]))
- set_nonblock(new_fd[0]);
- if (!isatty(new_fd[1]))
- set_nonblock(new_fd[1]);
-
- nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1]);
+ nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1],
+ CHANNEL_NONBLOCK_STDIO);
free(chost);
nc->ctl_chan = c->self; /* link session -> control channel */
- c->remote_id = nc->self; /* link control -> session channel */
+ c->remote_id = nc->self; /* link control -> session channel */
c->have_remote_id = 1;
- debug2("%s: channel_new: %d linked to control channel %d",
- __func__, nc->self, nc->ctl_chan);
+ debug2_f("channel_new: %d control %d", nc->self, nc->ctl_chan);
channel_register_cleanup(ssh, nc->self,
mux_master_session_cleanup_cb, 1);
@@ -1071,38 +1047,38 @@ mux_stdio_confirm(struct ssh *ssh, int id, int success, void *arg)
int r;
if (cctx == NULL)
- fatal("%s: cctx == NULL", __func__);
+ fatal_f("cctx == NULL");
if ((c = channel_by_id(ssh, id)) == NULL)
- fatal("%s: no channel for id %d", __func__, id);
+ fatal_f("no channel for id %d", id);
if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL)
- fatal("%s: channel %d lacks control channel %d", __func__,
+ fatal_f("channel %d lacks control channel %d",
id, c->ctl_chan);
if ((reply = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if (!success) {
- debug3("%s: sending failure reply", __func__);
+ debug3_f("sending failure reply");
reply_error(reply, MUX_S_FAILURE, cctx->rid,
"Session open refused by peer");
/* prepare reply */
goto done;
}
- debug3("%s: sending success reply", __func__);
+ debug3_f("sending success reply");
/* prepare reply */
if ((r = sshbuf_put_u32(reply, MUX_S_SESSION_OPENED)) != 0 ||
(r = sshbuf_put_u32(reply, cctx->rid)) != 0 ||
(r = sshbuf_put_u32(reply, c->self)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
done:
/* Send reply */
if ((r = sshbuf_put_stringb(cc->output, reply)) != 0)
- fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r));
+ fatal_fr(r, "enqueue");
sshbuf_free(reply);
if (cc->mux_pause <= 0)
- fatal("%s: mux_pause %d", __func__, cc->mux_pause);
+ fatal_f("mux_pause %d", cc->mux_pause);
cc->mux_pause = 0; /* start processing messages again */
c->open_confirm_ctx = NULL;
free(cctx);
@@ -1112,13 +1088,13 @@ static int
mux_master_process_stop_listening(struct ssh *ssh, u_int rid,
Channel *c, struct sshbuf *m, struct sshbuf *reply)
{
- debug("%s: channel %d: stop listening", __func__, c->self);
+ debug_f("channel %d: stop listening", c->self);
if (options.control_master == SSHCTL_MASTER_ASK ||
options.control_master == SSHCTL_MASTER_AUTO_ASK) {
if (!ask_permission("Disable further multiplexing on shared "
"connection to %s? ", host)) {
- debug2("%s: stop listen refused by user", __func__);
+ debug2_f("stop listen refused by user");
reply_error(reply, MUX_S_PERMISSION_DENIED, rid,
"Permission denied");
return 0;
@@ -1144,17 +1120,17 @@ mux_master_process_proxy(struct ssh *ssh, u_int rid,
{
int r;
- debug("%s: channel %d: proxy request", __func__, c->self);
+ debug_f("channel %d: proxy request", c->self);
c->mux_rcb = channel_proxy_downstream;
if ((r = sshbuf_put_u32(reply, MUX_S_PROXY)) != 0 ||
(r = sshbuf_put_u32(reply, rid)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
return 0;
}
-/* Channel callbacks fired on read/write from mux slave fd */
+/* Channel callbacks fired on read/write from mux client fd */
static int
mux_master_read_cb(struct ssh *ssh, Channel *c)
{
@@ -1164,7 +1140,7 @@ mux_master_read_cb(struct ssh *ssh, Channel *c)
int r, ret = -1;
if ((out = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
/* Setup ctx and */
if (c->mux_ctx == NULL) {
@@ -1176,12 +1152,11 @@ mux_master_read_cb(struct ssh *ssh, Channel *c)
/* Send hello */
if ((r = sshbuf_put_u32(out, MUX_MSG_HELLO)) != 0 ||
(r = sshbuf_put_u32(out, SSHMUX_VER)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
/* no extensions */
if ((r = sshbuf_put_stringb(c->output, out)) != 0)
- fatal("%s: sshbuf_put_stringb: %s",
- __func__, ssh_err(r));
- debug3("%s: channel %d: hello sent", __func__, c->self);
+ fatal_fr(r, "enqueue");
+ debug3_f("channel %d: hello sent", c->self);
ret = 0;
goto out;
}
@@ -1189,21 +1164,21 @@ mux_master_read_cb(struct ssh *ssh, Channel *c)
/* Channel code ensures that we receive whole packets */
if ((r = sshbuf_froms(c->input, &in)) != 0) {
malf:
- error("%s: malformed message", __func__);
+ error_f("malformed message");
goto out;
}
if ((r = sshbuf_get_u32(in, &type)) != 0)
goto malf;
- debug3("%s: channel %d packet type 0x%08x len %zu",
- __func__, c->self, type, sshbuf_len(in));
+ debug3_f("channel %d packet type 0x%08x len %zu", c->self,
+ type, sshbuf_len(in));
if (type == MUX_MSG_HELLO)
rid = 0;
else {
if (!state->hello_rcvd) {
- error("%s: expected MUX_MSG_HELLO(0x%08x), "
- "received 0x%08x", __func__, MUX_MSG_HELLO, type);
+ error_f("expected MUX_MSG_HELLO(0x%08x), "
+ "received 0x%08x", MUX_MSG_HELLO, type);
goto out;
}
if ((r = sshbuf_get_u32(in, &rid)) != 0)
@@ -1218,16 +1193,14 @@ mux_master_read_cb(struct ssh *ssh, Channel *c)
}
}
if (mux_master_handlers[i].handler == NULL) {
- error("%s: unsupported mux message 0x%08x", __func__, type);
+ error_f("unsupported mux message 0x%08x", type);
reply_error(out, MUX_S_FAILURE, rid, "unsupported request");
ret = 0;
}
/* Enqueue reply packet */
- if (sshbuf_len(out) != 0) {
- if ((r = sshbuf_put_stringb(c->output, out)) != 0)
- fatal("%s: sshbuf_put_stringb: %s",
- __func__, ssh_err(r));
- }
+ if (sshbuf_len(out) != 0 &&
+ (r = sshbuf_put_stringb(c->output, out)) != 0)
+ fatal_fr(r, "enqueue");
out:
sshbuf_free(in);
sshbuf_free(out);
@@ -1241,21 +1214,19 @@ mux_exit_message(struct ssh *ssh, Channel *c, int exitval)
Channel *mux_chan;
int r;
- debug3("%s: channel %d: exit message, exitval %d", __func__, c->self,
- exitval);
+ debug3_f("channel %d: exit message, exitval %d", c->self, exitval);
if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL)
- fatal("%s: channel %d missing mux channel %d",
- __func__, c->self, c->ctl_chan);
+ fatal_f("channel %d missing mux %d", c->self, c->ctl_chan);
/* Append exit message packet to control socket output queue */
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, MUX_S_EXIT_MESSAGE)) != 0 ||
(r = sshbuf_put_u32(m, c->self)) != 0 ||
(r = sshbuf_put_u32(m, exitval)) != 0 ||
(r = sshbuf_put_stringb(mux_chan->output, m)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
sshbuf_free(m);
}
@@ -1266,19 +1237,18 @@ mux_tty_alloc_failed(struct ssh *ssh, Channel *c)
Channel *mux_chan;
int r;
- debug3("%s: channel %d: TTY alloc failed", __func__, c->self);
+ debug3_f("channel %d: TTY alloc failed", c->self);
if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL)
- fatal("%s: channel %d missing mux channel %d",
- __func__, c->self, c->ctl_chan);
+ fatal_f("channel %d missing mux %d", c->self, c->ctl_chan);
/* Append exit message packet to control socket output queue */
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, MUX_S_TTY_ALLOC_FAIL)) != 0 ||
(r = sshbuf_put_u32(m, c->self)) != 0 ||
(r = sshbuf_put_stringb(mux_chan->output, m)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
sshbuf_free(m);
}
@@ -1313,7 +1283,7 @@ muxserver_listen(struct ssh *ssh)
rbuf[sizeof(rbuf) - 1] = '\0';
options.control_path = NULL;
xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf);
- debug3("%s: temporary control path %s", __func__, options.control_path);
+ debug3_f("temporary control path %s", options.control_path);
old_umask = umask(0177);
muxserver_sock = unix_listener(options.control_path, 64, 0);
@@ -1342,7 +1312,7 @@ muxserver_listen(struct ssh *ssh)
/* Now atomically "move" the mux socket into position */
if (link(options.control_path, orig_control_path) != 0) {
if (errno != EEXIST) {
- fatal("%s: link mux listener %s => %s: %s", __func__,
+ fatal_f("link mux listener %s => %s: %s",
options.control_path, orig_control_path,
strerror(errno));
}
@@ -1362,7 +1332,7 @@ muxserver_listen(struct ssh *ssh)
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
0, options.control_path, 1);
mux_listener_channel->mux_rcb = mux_master_read_cb;
- debug3("%s: mux listener channel %d fd %d", __func__,
+ debug3_f("mux listener channel %d fd %d",
mux_listener_channel->self, mux_listener_channel->sock);
}
@@ -1377,17 +1347,17 @@ mux_session_confirm(struct ssh *ssh, int id, int success, void *arg)
struct sshbuf *reply;
if (cctx == NULL)
- fatal("%s: cctx == NULL", __func__);
+ fatal_f("cctx == NULL");
if ((c = channel_by_id(ssh, id)) == NULL)
- fatal("%s: no channel for id %d", __func__, id);
+ fatal_f("no channel for id %d", id);
if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL)
- fatal("%s: channel %d lacks control channel %d", __func__,
+ fatal_f("channel %d lacks control channel %d",
id, c->ctl_chan);
if ((reply = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if (!success) {
- debug3("%s: sending failure reply", __func__);
+ debug3_f("sending failure reply");
reply_error(reply, MUX_S_FAILURE, cctx->rid,
"Session open refused by peer");
goto done;
@@ -1416,27 +1386,27 @@ mux_session_confirm(struct ssh *ssh, int id, int success, void *arg)
debug("Requesting authentication agent forwarding.");
channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0);
if ((r = sshpkt_send(ssh)) != 0)
- fatal("%s: packet error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send");
}
client_session2_setup(ssh, id, cctx->want_tty, cctx->want_subsys,
cctx->term, &cctx->tio, c->rfd, cctx->cmd, cctx->env);
- debug3("%s: sending success reply", __func__);
+ debug3_f("sending success reply");
/* prepare reply */
if ((r = sshbuf_put_u32(reply, MUX_S_SESSION_OPENED)) != 0 ||
(r = sshbuf_put_u32(reply, cctx->rid)) != 0 ||
(r = sshbuf_put_u32(reply, c->self)) != 0)
- fatal("%s: reply: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reply");
done:
/* Send reply */
if ((r = sshbuf_put_stringb(cc->output, reply)) != 0)
- fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r));
+ fatal_fr(r, "enqueue");
sshbuf_free(reply);
if (cc->mux_pause <= 0)
- fatal("%s: mux_pause %d", __func__, cc->mux_pause);
+ fatal_f("mux_pause %d", cc->mux_pause);
cc->mux_pause = 0; /* start processing messages again */
c->open_confirm_ctx = NULL;
sshbuf_free(cctx->cmd);
@@ -1485,7 +1455,7 @@ mux_client_read(int fd, struct sshbuf *b, size_t need)
pfd.fd = fd;
pfd.events = POLLIN;
if ((r = sshbuf_reserve(b, need, &p)) != 0)
- fatal("%s: reserve: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reserve");
for (have = 0; have < need; ) {
if (muxclient_terminate) {
errno = EINTR;
@@ -1527,9 +1497,9 @@ mux_client_write_packet(int fd, struct sshbuf *m)
pfd.fd = fd;
pfd.events = POLLOUT;
if ((queue = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_stringb(queue, m)) != 0)
- fatal("%s: sshbuf_put_stringb: %s", __func__, ssh_err(r));
+ fatal_fr(r, "enqueue");
need = sshbuf_len(queue);
ptr = sshbuf_ptr(queue);
@@ -1578,10 +1548,10 @@ mux_client_read_packet(int fd, struct sshbuf *m)
int r, oerrno;
if ((queue = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if (mux_client_read(fd, queue, 4) != 0) {
if ((oerrno = errno) == EPIPE)
- debug3("%s: read header failed: %s", __func__,
+ debug3_f("read header failed: %s",
strerror(errno));
sshbuf_free(queue);
errno = oerrno;
@@ -1590,14 +1560,14 @@ mux_client_read_packet(int fd, struct sshbuf *m)
need = PEEK_U32(sshbuf_ptr(queue));
if (mux_client_read(fd, queue, need) != 0) {
oerrno = errno;
- debug3("%s: read body failed: %s", __func__, strerror(errno));
+ debug3_f("read body failed: %s", strerror(errno));
sshbuf_free(queue);
errno = oerrno;
return -1;
}
if ((r = sshbuf_get_string_direct(queue, &ptr, &have)) != 0 ||
(r = sshbuf_put(m, ptr, have)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "dequeue");
sshbuf_free(queue);
return 0;
}
@@ -1610,14 +1580,14 @@ mux_client_hello_exchange(int fd)
int r, ret = -1;
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, MUX_MSG_HELLO)) != 0 ||
(r = sshbuf_put_u32(m, SSHMUX_VER)) != 0)
- fatal("%s: hello: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble hello");
/* no extensions */
if (mux_client_write_packet(fd, m) != 0) {
- debug("%s: write packet: %s", __func__, strerror(errno));
+ debug_f("write packet: %s", strerror(errno));
goto out;
}
@@ -1625,33 +1595,31 @@ mux_client_hello_exchange(int fd)
/* Read their HELLO */
if (mux_client_read_packet(fd, m) != 0) {
- debug("%s: read packet failed", __func__);
+ debug_f("read packet failed");
goto out;
}
if ((r = sshbuf_get_u32(m, &type)) != 0)
- fatal("%s: decode type: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse type");
if (type != MUX_MSG_HELLO) {
- error("%s: expected HELLO (%u) received %u",
- __func__, MUX_MSG_HELLO, type);
+ error_f("expected HELLO (%u) got %u", MUX_MSG_HELLO, type);
goto out;
}
if ((r = sshbuf_get_u32(m, &ver)) != 0)
- fatal("%s: decode version: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse version");
if (ver != SSHMUX_VER) {
error("Unsupported multiplexing protocol version %d "
"(expected %d)", ver, SSHMUX_VER);
goto out;
}
- debug2("%s: master version %u", __func__, ver);
+ debug2_f("master version %u", ver);
/* No extensions are presently defined */
while (sshbuf_len(m) > 0) {
char *name = NULL;
if ((r = sshbuf_get_cstring(m, &name, NULL)) != 0 ||
(r = sshbuf_skip_string(m)) != 0) { /* value */
- error("%s: malformed extension: %s",
- __func__, ssh_err(r));
+ error_fr(r, "parse extension");
goto out;
}
debug2("Unrecognised master extension \"%s\"", name);
@@ -1672,16 +1640,16 @@ mux_client_request_alive(int fd)
u_int pid, type, rid;
int r;
- debug3("%s: entering", __func__);
+ debug3_f("entering");
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, MUX_C_ALIVE_CHECK)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0)
- fatal("%s: request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "assemble");
if (mux_client_write_packet(fd, m) != 0)
- fatal("%s: write packet: %s", __func__, strerror(errno));
+ fatal_f("write packet: %s", strerror(errno));
sshbuf_reset(m);
@@ -1692,23 +1660,23 @@ mux_client_request_alive(int fd)
}
if ((r = sshbuf_get_u32(m, &type)) != 0)
- fatal("%s: decode type: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse type");
if (type != MUX_S_ALIVE) {
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
- fatal("%s: master returned error: %s", __func__, e);
+ fatal_fr(r, "parse error message");
+ fatal_f("master returned error: %s", e);
}
if ((r = sshbuf_get_u32(m, &rid)) != 0)
- fatal("%s: decode remote ID: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse remote ID");
if (rid != muxclient_request_id)
- fatal("%s: out of sequence reply: my id %u theirs %u",
- __func__, muxclient_request_id, rid);
+ fatal_f("out of sequence reply: my id %u theirs %u",
+ muxclient_request_id, rid);
if ((r = sshbuf_get_u32(m, &pid)) != 0)
- fatal("%s: decode PID: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse PID");
sshbuf_free(m);
- debug3("%s: done pid = %u", __func__, pid);
+ debug3_f("done pid = %u", pid);
muxclient_request_id++;
@@ -1723,16 +1691,16 @@ mux_client_request_terminate(int fd)
u_int type, rid;
int r;
- debug3("%s: entering", __func__);
+ debug3_f("entering");
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, MUX_C_TERMINATE)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0)
- fatal("%s: request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "request");
if (mux_client_write_packet(fd, m) != 0)
- fatal("%s: write packet: %s", __func__, strerror(errno));
+ fatal_f("write packet: %s", strerror(errno));
sshbuf_reset(m);
@@ -1743,30 +1711,28 @@ mux_client_request_terminate(int fd)
sshbuf_free(m);
return;
}
- fatal("%s: read from master failed: %s",
- __func__, strerror(errno));
+ fatal_f("read from master failed: %s", strerror(errno));
}
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_u32(m, &rid)) != 0)
- fatal("%s: decode: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (rid != muxclient_request_id)
- fatal("%s: out of sequence reply: my id %u theirs %u",
- __func__, muxclient_request_id, rid);
+ fatal_f("out of sequence reply: my id %u theirs %u",
+ muxclient_request_id, rid);
switch (type) {
case MUX_S_OK:
break;
case MUX_S_PERMISSION_DENIED:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse error message");
fatal("Master refused termination request: %s", e);
case MUX_S_FAILURE:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
- fatal("%s: termination request failed: %s", __func__, e);
+ fatal_fr(r, "parse error message");
+ fatal_f("termination request failed: %s", e);
default:
- fatal("%s: unexpected response from master 0x%08x",
- __func__, type);
+ fatal_f("unexpected response from master 0x%08x", type);
}
sshbuf_free(m);
muxclient_request_id++;
@@ -1804,7 +1770,7 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd)
chost = fwd->connect_host;
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, type)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0 ||
(r = sshbuf_put_u32(m, ftype)) != 0 ||
@@ -1812,10 +1778,10 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd)
(r = sshbuf_put_u32(m, fwd->listen_port)) != 0 ||
(r = sshbuf_put_cstring(m, chost)) != 0 ||
(r = sshbuf_put_u32(m, fwd->connect_port)) != 0)
- fatal("%s: request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "request");
if (mux_client_write_packet(fd, m) != 0)
- fatal("%s: write packet: %s", __func__, strerror(errno));
+ fatal_f("write packet: %s", strerror(errno));
sshbuf_reset(m);
@@ -1827,19 +1793,19 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd)
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_u32(m, &rid)) != 0)
- fatal("%s: decode: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (rid != muxclient_request_id)
- fatal("%s: out of sequence reply: my id %u theirs %u",
- __func__, muxclient_request_id, rid);
+ fatal_f("out of sequence reply: my id %u theirs %u",
+ muxclient_request_id, rid);
switch (type) {
case MUX_S_OK:
break;
case MUX_S_REMOTE_PORT:
if (cancel_flag)
- fatal("%s: got MUX_S_REMOTE_PORT for cancel", __func__);
+ fatal_f("got MUX_S_REMOTE_PORT for cancel");
if ((r = sshbuf_get_u32(m, &fwd->allocated_port)) != 0)
- fatal("%s: decode port: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse port");
verbose("Allocated port %u for remote forward to %s:%d",
fwd->allocated_port,
fwd->connect_host ? fwd->connect_host : "",
@@ -1849,19 +1815,18 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd)
break;
case MUX_S_PERMISSION_DENIED:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse error message");
sshbuf_free(m);
error("Master refused forwarding request: %s", e);
return -1;
case MUX_S_FAILURE:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse error message");
sshbuf_free(m);
- error("%s: forwarding request failed: %s", __func__, e);
+ error_f("forwarding request failed: %s", e);
return -1;
default:
- fatal("%s: unexpected response from master 0x%08x",
- __func__, type);
+ fatal_f("unexpected response from master 0x%08x", type);
}
sshbuf_free(m);
@@ -1874,7 +1839,7 @@ mux_client_forwards(int fd, int cancel_flag)
{
int i, ret = 0;
- debug3("%s: %s forwardings: %d local, %d remote", __func__,
+ debug3_f("%s forwardings: %d local, %d remote",
cancel_flag ? "cancel" : "request",
options.num_local_forwards, options.num_remote_forwards);
@@ -1899,48 +1864,44 @@ mux_client_request_session(int fd)
{
struct sshbuf *m;
char *e;
- const char *term;
+ const char *term = NULL;
u_int echar, rid, sid, esid, exitval, type, exitval_seen;
extern char **environ;
- int r, i, devnull, rawmode;
+ int r, i, rawmode;
- debug3("%s: entering", __func__);
+ debug3_f("entering");
if ((muxserver_pid = mux_client_request_alive(fd)) == 0) {
- error("%s: master alive request failed", __func__);
+ error_f("master alive request failed");
return -1;
}
ssh_signal(SIGPIPE, SIG_IGN);
- if (stdin_null_flag) {
- if ((devnull = open(_PATH_DEVNULL, O_RDONLY)) == -1)
- fatal("open(/dev/null): %s", strerror(errno));
- if (dup2(devnull, STDIN_FILENO) == -1)
- fatal("dup2: %s", strerror(errno));
- if (devnull > STDERR_FILENO)
- close(devnull);
- }
+ if (options.stdin_null && stdfd_devnull(1, 0, 0) == -1)
+ fatal_f("stdfd_devnull failed");
+
+ if ((term = lookup_env_in_list("TERM", options.setenv,
+ options.num_setenv)) == NULL || *term == '\0')
+ term = getenv("TERM");
- if ((term = getenv("TERM")) == NULL)
- term = "";
echar = 0xffffffff;
if (options.escape_char != SSH_ESCAPECHAR_NONE)
echar = (u_int)options.escape_char;
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, MUX_C_NEW_SESSION)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0 ||
(r = sshbuf_put_string(m, NULL, 0)) != 0 || /* reserved */
(r = sshbuf_put_u32(m, tty_flag)) != 0 ||
(r = sshbuf_put_u32(m, options.forward_x11)) != 0 ||
(r = sshbuf_put_u32(m, options.forward_agent)) != 0 ||
- (r = sshbuf_put_u32(m, subsystem_flag)) != 0 ||
+ (r = sshbuf_put_u32(m, options.session_type == SESSION_TYPE_SUBSYSTEM)) != 0 ||
(r = sshbuf_put_u32(m, echar)) != 0 ||
- (r = sshbuf_put_cstring(m, term)) != 0 ||
+ (r = sshbuf_put_cstring(m, term == NULL ? "" : term)) != 0 ||
(r = sshbuf_put_stringb(m, command)) != 0)
- fatal("%s: request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "request");
/* Pass environment */
if (options.num_send_env > 0 && environ != NULL) {
@@ -1948,69 +1909,67 @@ mux_client_request_session(int fd)
if (!env_permitted(environ[i]))
continue;
if ((r = sshbuf_put_cstring(m, environ[i])) != 0)
- fatal("%s: request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "request sendenv");
}
}
for (i = 0; i < options.num_setenv; i++) {
if ((r = sshbuf_put_cstring(m, options.setenv[i])) != 0)
- fatal("%s: request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "request setenv");
}
if (mux_client_write_packet(fd, m) != 0)
- fatal("%s: write packet: %s", __func__, strerror(errno));
+ fatal_f("write packet: %s", strerror(errno));
/* Send the stdio file descriptors */
if (mm_send_fd(fd, STDIN_FILENO) == -1 ||
mm_send_fd(fd, STDOUT_FILENO) == -1 ||
mm_send_fd(fd, STDERR_FILENO) == -1)
- fatal("%s: send fds failed", __func__);
+ fatal_f("send fds failed");
- debug3("%s: session request sent", __func__);
+ debug3_f("session request sent");
/* Read their reply */
sshbuf_reset(m);
if (mux_client_read_packet(fd, m) != 0) {
- error("%s: read from master failed: %s",
- __func__, strerror(errno));
+ error_f("read from master failed: %s", strerror(errno));
sshbuf_free(m);
return -1;
}
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_u32(m, &rid)) != 0)
- fatal("%s: decode: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (rid != muxclient_request_id)
- fatal("%s: out of sequence reply: my id %u theirs %u",
- __func__, muxclient_request_id, rid);
+ fatal_f("out of sequence reply: my id %u theirs %u",
+ muxclient_request_id, rid);
switch (type) {
case MUX_S_SESSION_OPENED:
if ((r = sshbuf_get_u32(m, &sid)) != 0)
- fatal("%s: decode ID: %s", __func__, ssh_err(r));
- debug("%s: master session id: %u", __func__, sid);
+ fatal_fr(r, "parse session ID");
+ debug_f("master session id: %u", sid);
break;
case MUX_S_PERMISSION_DENIED:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse error message");
error("Master refused session request: %s", e);
sshbuf_free(m);
return -1;
case MUX_S_FAILURE:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
- error("%s: session request failed: %s", __func__, e);
+ fatal_fr(r, "parse error message");
+ error_f("session request failed: %s", e);
sshbuf_free(m);
return -1;
default:
sshbuf_free(m);
- error("%s: unexpected response from master 0x%08x",
- __func__, type);
+ error_f("unexpected response from master 0x%08x", type);
return -1;
}
muxclient_request_id++;
if (pledge("stdio proc tty", NULL) == -1)
- fatal("%s pledge(): %s", __func__, strerror(errno));
+ fatal_f("pledge(): %s", strerror(errno));
platform_pledge_mux();
ssh_signal(SIGHUP, control_client_sighandler);
@@ -2034,40 +1993,34 @@ mux_client_request_session(int fd)
if (mux_client_read_packet(fd, m) != 0)
break;
if ((r = sshbuf_get_u32(m, &type)) != 0)
- fatal("%s: decode type: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse type");
switch (type) {
case MUX_S_TTY_ALLOC_FAIL:
if ((r = sshbuf_get_u32(m, &esid)) != 0)
- fatal("%s: decode ID: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "parse session ID");
if (esid != sid)
- fatal("%s: tty alloc fail on unknown session: "
- "my id %u theirs %u",
- __func__, sid, esid);
+ fatal_f("tty alloc fail on unknown session: "
+ "my id %u theirs %u", sid, esid);
leave_raw_mode(options.request_tty ==
REQUEST_TTY_FORCE);
rawmode = 0;
continue;
case MUX_S_EXIT_MESSAGE:
if ((r = sshbuf_get_u32(m, &esid)) != 0)
- fatal("%s: decode ID: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "parse session ID");
if (esid != sid)
- fatal("%s: exit on unknown session: "
- "my id %u theirs %u",
- __func__, sid, esid);
+ fatal_f("exit on unknown session: "
+ "my id %u theirs %u", sid, esid);
if (exitval_seen)
- fatal("%s: exitval sent twice", __func__);
+ fatal_f("exitval sent twice");
if ((r = sshbuf_get_u32(m, &exitval)) != 0)
- fatal("%s: decode exit value: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "parse exitval");
exitval_seen = 1;
continue;
default:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s",
- __func__, ssh_err(r));
- fatal("%s: master returned error: %s", __func__, e);
+ fatal_fr(r, "parse error message");
+ fatal_f("master returned error: %s", e);
}
}
@@ -2099,12 +2052,12 @@ mux_client_proxy(int fd)
int r;
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, MUX_C_PROXY)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0)
- fatal("%s: request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "request");
if (mux_client_write_packet(fd, m) != 0)
- fatal("%s: write packet: %s", __func__, strerror(errno));
+ fatal_f("write packet: %s", strerror(errno));
sshbuf_reset(m);
@@ -2115,18 +2068,18 @@ mux_client_proxy(int fd)
}
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_u32(m, &rid)) != 0)
- fatal("%s: decode: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (rid != muxclient_request_id)
- fatal("%s: out of sequence reply: my id %u theirs %u",
- __func__, muxclient_request_id, rid);
+ fatal_f("out of sequence reply: my id %u theirs %u",
+ muxclient_request_id, rid);
if (type != MUX_S_PROXY) {
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
- fatal("%s: master returned error: %s", __func__, e);
+ fatal_fr(r, "parse error message");
+ fatal_f("master returned error: %s", e);
}
sshbuf_free(m);
- debug3("%s: done", __func__);
+ debug3_f("done");
muxclient_request_id++;
return 0;
}
@@ -2137,85 +2090,77 @@ mux_client_request_stdio_fwd(int fd)
struct sshbuf *m;
char *e;
u_int type, rid, sid;
- int r, devnull;
+ int r;
- debug3("%s: entering", __func__);
+ debug3_f("entering");
if ((muxserver_pid = mux_client_request_alive(fd)) == 0) {
- error("%s: master alive request failed", __func__);
+ error_f("master alive request failed");
return -1;
}
ssh_signal(SIGPIPE, SIG_IGN);
- if (stdin_null_flag) {
- if ((devnull = open(_PATH_DEVNULL, O_RDONLY)) == -1)
- fatal("open(/dev/null): %s", strerror(errno));
- if (dup2(devnull, STDIN_FILENO) == -1)
- fatal("dup2: %s", strerror(errno));
- if (devnull > STDERR_FILENO)
- close(devnull);
- }
+ if (options.stdin_null && stdfd_devnull(1, 0, 0) == -1)
+ fatal_f("stdfd_devnull failed");
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, MUX_C_NEW_STDIO_FWD)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0 ||
(r = sshbuf_put_string(m, NULL, 0)) != 0 || /* reserved */
(r = sshbuf_put_cstring(m, options.stdio_forward_host)) != 0 ||
(r = sshbuf_put_u32(m, options.stdio_forward_port)) != 0)
- fatal("%s: request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "request");
if (mux_client_write_packet(fd, m) != 0)
- fatal("%s: write packet: %s", __func__, strerror(errno));
+ fatal_f("write packet: %s", strerror(errno));
/* Send the stdio file descriptors */
if (mm_send_fd(fd, STDIN_FILENO) == -1 ||
mm_send_fd(fd, STDOUT_FILENO) == -1)
- fatal("%s: send fds failed", __func__);
+ fatal_f("send fds failed");
if (pledge("stdio proc tty", NULL) == -1)
- fatal("%s pledge(): %s", __func__, strerror(errno));
+ fatal_f("pledge(): %s", strerror(errno));
platform_pledge_mux();
- debug3("%s: stdio forward request sent", __func__);
+ debug3_f("stdio forward request sent");
/* Read their reply */
sshbuf_reset(m);
if (mux_client_read_packet(fd, m) != 0) {
- error("%s: read from master failed: %s",
- __func__, strerror(errno));
+ error_f("read from master failed: %s", strerror(errno));
sshbuf_free(m);
return -1;
}
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_u32(m, &rid)) != 0)
- fatal("%s: decode: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (rid != muxclient_request_id)
- fatal("%s: out of sequence reply: my id %u theirs %u",
- __func__, muxclient_request_id, rid);
+ fatal_f("out of sequence reply: my id %u theirs %u",
+ muxclient_request_id, rid);
switch (type) {
case MUX_S_SESSION_OPENED:
if ((r = sshbuf_get_u32(m, &sid)) != 0)
- fatal("%s: decode ID: %s", __func__, ssh_err(r));
- debug("%s: master session id: %u", __func__, sid);
+ fatal_fr(r, "parse session ID");
+ debug_f("master session id: %u", sid);
break;
case MUX_S_PERMISSION_DENIED:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse error message");
sshbuf_free(m);
fatal("Master refused stdio forwarding request: %s", e);
case MUX_S_FAILURE:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse error message");
sshbuf_free(m);
fatal("Stdio forwarding request failed: %s", e);
default:
sshbuf_free(m);
- error("%s: unexpected response from master 0x%08x",
- __func__, type);
+ error_f("unexpected response from master 0x%08x", type);
return -1;
}
muxclient_request_id++;
@@ -2233,10 +2178,9 @@ mux_client_request_stdio_fwd(int fd)
if (errno == EPIPE ||
(errno == EINTR && muxclient_terminate != 0))
return 0;
- fatal("%s: mux_client_read_packet: %s",
- __func__, strerror(errno));
+ fatal_f("mux_client_read_packet: %s", strerror(errno));
}
- fatal("%s: master returned unexpected message %u", __func__, type);
+ fatal_f("master returned unexpected message %u", type);
}
static void
@@ -2247,45 +2191,43 @@ mux_client_request_stop_listening(int fd)
u_int type, rid;
int r;
- debug3("%s: entering", __func__);
+ debug3_f("entering");
if ((m = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if ((r = sshbuf_put_u32(m, MUX_C_STOP_LISTENING)) != 0 ||
(r = sshbuf_put_u32(m, muxclient_request_id)) != 0)
- fatal("%s: request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "request");
if (mux_client_write_packet(fd, m) != 0)
- fatal("%s: write packet: %s", __func__, strerror(errno));
+ fatal_f("write packet: %s", strerror(errno));
sshbuf_reset(m);
/* Read their reply */
if (mux_client_read_packet(fd, m) != 0)
- fatal("%s: read from master failed: %s",
- __func__, strerror(errno));
+ fatal_f("read from master failed: %s", strerror(errno));
if ((r = sshbuf_get_u32(m, &type)) != 0 ||
(r = sshbuf_get_u32(m, &rid)) != 0)
- fatal("%s: decode: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (rid != muxclient_request_id)
- fatal("%s: out of sequence reply: my id %u theirs %u",
- __func__, muxclient_request_id, rid);
+ fatal_f("out of sequence reply: my id %u theirs %u",
+ muxclient_request_id, rid);
switch (type) {
case MUX_S_OK:
break;
case MUX_S_PERMISSION_DENIED:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse error message");
fatal("Master refused stop listening request: %s", e);
case MUX_S_FAILURE:
if ((r = sshbuf_get_cstring(m, &e, NULL)) != 0)
- fatal("%s: decode error: %s", __func__, ssh_err(r));
- fatal("%s: stop listening request failed: %s", __func__, e);
+ fatal_fr(r, "parse error message");
+ fatal_f("stop listening request failed: %s", e);
default:
- fatal("%s: unexpected response from master 0x%08x",
- __func__, type);
+ fatal_f("unexpected response from master 0x%08x", type);
}
sshbuf_free(m);
muxclient_request_id++;
@@ -2323,10 +2265,10 @@ muxclient(const char *path)
if (strlcpy(addr.sun_path, path,
sizeof(addr.sun_path)) >= sizeof(addr.sun_path))
fatal("ControlPath too long ('%s' >= %u bytes)", path,
- (unsigned int)sizeof(addr.sun_path));
+ (unsigned int)sizeof(addr.sun_path));
if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
- fatal("%s socket(): %s", __func__, strerror(errno));
+ fatal_f("socket(): %s", strerror(errno));
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
switch (muxclient_command) {
@@ -2353,7 +2295,7 @@ muxclient(const char *path)
set_nonblock(sock);
if (mux_client_hello_exchange(sock) != 0) {
- error("%s: master hello exchange failed", __func__);
+ error_f("master hello exchange failed");
close(sock);
return -1;
}
@@ -2361,7 +2303,7 @@ muxclient(const char *path)
switch (muxclient_command) {
case SSHMUX_COMMAND_ALIVE_CHECK:
if ((pid = mux_client_request_alive(sock)) == 0)
- fatal("%s: master alive check failed", __func__);
+ fatal_f("master alive check failed");
fprintf(stderr, "Master running (pid=%u)\r\n", pid);
exit(0);
case SSHMUX_COMMAND_TERMINATE:
@@ -2371,11 +2313,11 @@ muxclient(const char *path)
exit(0);
case SSHMUX_COMMAND_FORWARD:
if (mux_client_forwards(sock, 0) != 0)
- fatal("%s: master forward request failed", __func__);
+ fatal_f("master forward request failed");
exit(0);
case SSHMUX_COMMAND_OPEN:
if (mux_client_forwards(sock, 0) != 0) {
- error("%s: master forward request failed", __func__);
+ error_f("master forward request failed");
return -1;
}
mux_client_request_session(sock);
@@ -2390,8 +2332,7 @@ muxclient(const char *path)
exit(0);
case SSHMUX_COMMAND_CANCEL_FWD:
if (mux_client_forwards(sock, 1) != 0)
- error("%s: master cancel forward request failed",
- __func__);
+ error_f("master cancel forward request failed");
exit(0);
case SSHMUX_COMMAND_PROXY:
mux_client_proxy(sock);
diff --git a/myproposal.h b/myproposal.h
index 5312e6058..6d79937b6 100644
--- a/myproposal.h
+++ b/myproposal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: myproposal.h,v 1.67 2020/01/24 00:28:57 djm Exp $ */
+/* $OpenBSD: myproposal.h,v 1.69 2021/08/29 23:53:10 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -38,24 +38,22 @@
#define KEX_CLIENT_KEX KEX_SERVER_KEX
#define KEX_DEFAULT_PK_ALG \
+ "ssh-ed25519-cert-v01@openssh.com," \
"ecdsa-sha2-nistp256-cert-v01@openssh.com," \
"ecdsa-sha2-nistp384-cert-v01@openssh.com," \
"ecdsa-sha2-nistp521-cert-v01@openssh.com," \
- "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com," \
- "ssh-ed25519-cert-v01@openssh.com," \
"sk-ssh-ed25519-cert-v01@openssh.com," \
+ "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com," \
"rsa-sha2-512-cert-v01@openssh.com," \
"rsa-sha2-256-cert-v01@openssh.com," \
- "ssh-rsa-cert-v01@openssh.com," \
+ "ssh-ed25519," \
"ecdsa-sha2-nistp256," \
"ecdsa-sha2-nistp384," \
"ecdsa-sha2-nistp521," \
- "sk-ecdsa-sha2-nistp256@openssh.com," \
- "ssh-ed25519," \
"sk-ssh-ed25519@openssh.com," \
+ "sk-ecdsa-sha2-nistp256@openssh.com," \
"rsa-sha2-512," \
- "rsa-sha2-256," \
- "ssh-rsa"
+ "rsa-sha2-256"
#define KEX_SERVER_ENCRYPT \
"chacha20-poly1305@openssh.com," \
@@ -80,12 +78,12 @@
/* Not a KEX value, but here so all the algorithm defaults are together */
#define SSH_ALLOWED_CA_SIGALGS \
+ "ssh-ed25519," \
"ecdsa-sha2-nistp256," \
"ecdsa-sha2-nistp384," \
"ecdsa-sha2-nistp521," \
- "sk-ecdsa-sha2-nistp256@openssh.com," \
- "ssh-ed25519," \
"sk-ssh-ed25519@openssh.com," \
+ "sk-ecdsa-sha2-nistp256@openssh.com," \
"rsa-sha2-512," \
"rsa-sha2-256"
diff --git a/nchan.c b/nchan.c
index 1e96eb641..7ef3a350b 100644
--- a/nchan.c
+++ b/nchan.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nchan.c,v 1.70 2019/06/28 13:35:04 deraadt Exp $ */
+/* $OpenBSD: nchan.c,v 1.73 2021/05/19 01:24:05 djm Exp $ */
/*
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
*
@@ -185,12 +185,11 @@ chan_send_eof2(struct ssh *ssh, Channel *c)
switch (c->istate) {
case CHAN_INPUT_WAIT_DRAIN:
if (!c->have_remote_id)
- fatal("%s: channel %d: no remote_id",
- __func__, c->self);
+ fatal_f("channel %d: no remote_id", c->self);
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EOF)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send CHANNEL_EOF");
c->flags |= CHAN_EOF_SENT;
break;
default:
@@ -214,12 +213,11 @@ chan_send_close2(struct ssh *ssh, Channel *c)
error("channel %d: already sent close", c->self);
} else {
if (!c->have_remote_id)
- fatal("%s: channel %d: no remote_id",
- __func__, c->self);
+ fatal_f("channel %d: no remote_id", c->self);
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_CLOSE)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send CHANNEL_EOF");
c->flags |= CHAN_CLOSE_SENT;
}
}
@@ -235,16 +233,16 @@ chan_send_eow2(struct ssh *ssh, Channel *c)
c->self);
return;
}
- if (!(datafellows & SSH_NEW_OPENSSH))
+ if (!(ssh->compat & SSH_NEW_OPENSSH))
return;
if (!c->have_remote_id)
- fatal("%s: channel %d: no remote_id", __func__, c->self);
+ fatal_f("channel %d: no remote_id", c->self);
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_put_cstring(ssh, "eow@openssh.com")) != 0 ||
(r = sshpkt_put_u8(ssh, 0)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send CHANNEL_EOF");
}
/* shared */
@@ -336,7 +334,7 @@ chan_is_dead(struct ssh *ssh, Channel *c, int do_send)
}
if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED)
return 0;
- if ((datafellows & SSH_BUG_EXTEOF) &&
+ if ((ssh->compat & SSH_BUG_EXTEOF) &&
c->extended_usage == CHAN_EXTENDED_WRITE &&
c->efd != -1 &&
sshbuf_len(c->extended) > 0) {
@@ -376,22 +374,20 @@ chan_shutdown_write(struct ssh *ssh, Channel *c)
if (c->type == SSH_CHANNEL_LARVAL)
return;
/* shutdown failure is allowed if write failed already */
- debug2("channel %d: %s (i%d o%d sock %d wfd %d efd %d [%s])",
- c->self, __func__, c->istate, c->ostate, c->sock, c->wfd, c->efd,
+ debug2_f("channel %d: (i%d o%d sock %d wfd %d efd %d [%s])",
+ c->self, c->istate, c->ostate, c->sock, c->wfd, c->efd,
channel_format_extended_usage(c));
if (c->sock != -1) {
if (shutdown(c->sock, SHUT_WR) == -1) {
- debug2("channel %d: %s: shutdown() failed for "
- "fd %d [i%d o%d]: %.100s", c->self, __func__,
- c->sock, c->istate, c->ostate,
- strerror(errno));
+ debug2_f("channel %d: shutdown() failed for "
+ "fd %d [i%d o%d]: %.100s", c->self, c->sock,
+ c->istate, c->ostate, strerror(errno));
}
} else {
- if (channel_close_fd(ssh, &c->wfd) < 0) {
- logit("channel %d: %s: close() failed for "
- "fd %d [i%d o%d]: %.100s",
- c->self, __func__, c->wfd, c->istate, c->ostate,
- strerror(errno));
+ if (channel_close_fd(ssh, c, &c->wfd) < 0) {
+ logit_f("channel %d: close() failed for "
+ "fd %d [i%d o%d]: %.100s", c->self, c->wfd,
+ c->istate, c->ostate, strerror(errno));
}
}
}
@@ -401,8 +397,8 @@ chan_shutdown_read(struct ssh *ssh, Channel *c)
{
if (c->type == SSH_CHANNEL_LARVAL)
return;
- debug2("channel %d: %s (i%d o%d sock %d wfd %d efd %d [%s])",
- c->self, __func__, c->istate, c->ostate, c->sock, c->rfd, c->efd,
+ debug2_f("channel %d: (i%d o%d sock %d wfd %d efd %d [%s])",
+ c->self, c->istate, c->ostate, c->sock, c->rfd, c->efd,
channel_format_extended_usage(c));
if (c->sock != -1) {
/*
@@ -411,17 +407,15 @@ chan_shutdown_read(struct ssh *ssh, Channel *c)
* HP-UX may return ENOTCONN also.
*/
if (shutdown(c->sock, SHUT_RD) == -1 && errno != ENOTCONN) {
- error("channel %d: %s: shutdown() failed for "
- "fd %d [i%d o%d]: %.100s",
- c->self, __func__, c->sock, c->istate, c->ostate,
- strerror(errno));
+ error_f("channel %d: shutdown() failed for "
+ "fd %d [i%d o%d]: %.100s", c->self, c->sock,
+ c->istate, c->ostate, strerror(errno));
}
} else {
- if (channel_close_fd(ssh, &c->rfd) < 0) {
- logit("channel %d: %s: close() failed for "
- "fd %d [i%d o%d]: %.100s",
- c->self, __func__, c->rfd, c->istate, c->ostate,
- strerror(errno));
+ if (channel_close_fd(ssh, c, &c->rfd) < 0) {
+ logit_f("channel %d: close() failed for "
+ "fd %d [i%d o%d]: %.100s", c->self, c->rfd,
+ c->istate, c->ostate, strerror(errno));
}
}
}
@@ -434,13 +428,12 @@ chan_shutdown_extended_read(struct ssh *ssh, Channel *c)
if (c->extended_usage != CHAN_EXTENDED_READ &&
c->extended_usage != CHAN_EXTENDED_IGNORE)
return;
- debug2("channel %d: %s (i%d o%d sock %d wfd %d efd %d [%s])",
- c->self, __func__, c->istate, c->ostate, c->sock, c->rfd, c->efd,
+ debug_f("channel %d: (i%d o%d sock %d wfd %d efd %d [%s])",
+ c->self, c->istate, c->ostate, c->sock, c->rfd, c->efd,
channel_format_extended_usage(c));
- if (channel_close_fd(ssh, &c->efd) < 0) {
- logit("channel %d: %s: close() failed for "
- "extended fd %d [i%d o%d]: %.100s",
- c->self, __func__, c->efd, c->istate, c->ostate,
- strerror(errno));
+ if (channel_close_fd(ssh, c, &c->efd) < 0) {
+ logit_f("channel %d: close() failed for "
+ "extended fd %d [i%d o%d]: %.100s", c->self, c->efd,
+ c->istate, c->ostate, strerror(errno));
}
}
diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in
index 3eb188f0b..5d53bef57 100644
--- a/openbsd-compat/Makefile.in
+++ b/openbsd-compat/Makefile.in
@@ -79,6 +79,7 @@ COMPAT= arc4random.o \
bsd-nextstep.o \
bsd-openpty.o \
bsd-poll.o \
+ bsd-pselect.o \
bsd-setres_id.o \
bsd-signal.o \
bsd-snprintf.o \
@@ -94,6 +95,7 @@ COMPAT= arc4random.o \
PORTS= port-aix.o \
port-irix.o \
port-linux.o \
+ port-prngd.o \
port-solaris.o \
port-net.o \
port-uw.o
diff --git a/openbsd-compat/arc4random.c b/openbsd-compat/arc4random.c
index 578f69f4f..14853aba4 100644
--- a/openbsd-compat/arc4random.c
+++ b/openbsd-compat/arc4random.c
@@ -88,7 +88,7 @@ _rs_init(u_char *buf, size_t n)
static void
getrnd(u_char *s, size_t len)
{
- int fd;
+ int fd, save_errno;
ssize_t r;
size_t o = 0;
@@ -97,8 +97,14 @@ getrnd(u_char *s, size_t len)
return;
#endif /* HAVE_GETRANDOM */
- if ((fd = open(SSH_RANDOM_DEV, O_RDONLY)) == -1)
- fatal("Couldn't open %s: %s", SSH_RANDOM_DEV, strerror(errno));
+ if ((fd = open(SSH_RANDOM_DEV, O_RDONLY)) == -1) {
+ save_errno = errno;
+ /* Try egd/prngd before giving up. */
+ if (seed_from_prngd(s, len) == 0)
+ return;
+ fatal("Couldn't open %s: %s", SSH_RANDOM_DEV,
+ strerror(save_errno));
+ }
while (o < len) {
r = read(fd, s + o, len - o);
if (r < 0) {
diff --git a/openbsd-compat/base64.c b/openbsd-compat/base64.c
index 9e7466716..b7dce095e 100644
--- a/openbsd-compat/base64.c
+++ b/openbsd-compat/base64.c
@@ -211,7 +211,7 @@ b64_pton(char const *src, u_char *target, size_t targsize)
break;
pos = strchr(Base64, ch);
- if (pos == 0) /* A non-base64 character. */
+ if (pos == 0) /* A non-base64 character. */
return (-1);
switch (state) {
diff --git a/openbsd-compat/bcrypt_pbkdf.c b/openbsd-compat/bcrypt_pbkdf.c
index 785234563..62728d38f 100644
--- a/openbsd-compat/bcrypt_pbkdf.c
+++ b/openbsd-compat/bcrypt_pbkdf.c
@@ -15,6 +15,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/* OPENBSD ORIGINAL: lib/libutil/bcrypt_pbkdf.c */
+
#include "includes.h"
#ifndef HAVE_BCRYPT_PBKDF
@@ -91,7 +93,7 @@ bcrypt_hash(u_int8_t *sha2pass, u_int8_t *sha2salt, u_int8_t *out)
cdata[i] = Blowfish_stream2word(ciphertext, sizeof(ciphertext),
&j);
for (i = 0; i < 64; i++)
- blf_enc(&state, cdata, sizeof(cdata) / sizeof(uint64_t));
+ blf_enc(&state, cdata, sizeof(cdata) / (sizeof(uint64_t)));
/* copy out */
for (i = 0; i < BCRYPT_WORDS; i++) {
diff --git a/openbsd-compat/bsd-misc.h b/openbsd-compat/bsd-misc.h
index 3a7dd6f4c..2206e1a82 100644
--- a/openbsd-compat/bsd-misc.h
+++ b/openbsd-compat/bsd-misc.h
@@ -20,6 +20,7 @@
#include "includes.h"
char *ssh_get_progname(char *);
+int seed_from_prngd(unsigned char *, size_t);
#ifndef HAVE_SETSID
#define setsid() setpgrp(0, getpid())
@@ -125,6 +126,11 @@ int isblank(int);
pid_t getpgid(pid_t);
#endif
+#ifndef HAVE_PSELECT
+int pselect(int, fd_set *, fd_set *, fd_set *, const struct timespec *,
+ const sigset_t *);
+#endif
+
#ifndef HAVE_ENDGRENT
# define endgrent() do { } while(0)
#endif
diff --git a/openbsd-compat/bsd-poll.h b/openbsd-compat/bsd-poll.h
index 17945f5b4..8420ca1db 100644
--- a/openbsd-compat/bsd-poll.h
+++ b/openbsd-compat/bsd-poll.h
@@ -32,7 +32,7 @@
#define _COMPAT_POLL_H_
typedef struct pollfd {
- int fd;
+ int fd;
short events;
short revents;
} pollfd_t;
diff --git a/openbsd-compat/bsd-pselect.c b/openbsd-compat/bsd-pselect.c
new file mode 100644
index 000000000..b36320863
--- /dev/null
+++ b/openbsd-compat/bsd-pselect.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2001 Markus Friedl. All rights reserved.
+ * Copyright (c) 2021 Darren Tucker (dtucker at dtucker net).
+ *
+ * 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"
+#ifndef HAVE_PSELECT
+
+#include <sys/types.h>
+#include <sys/time.h>
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "log.h"
+#include "misc.h" /* for set_nonblock */
+
+#ifndef HAVE_SIGHANDLER_T
+typedef void (*sighandler_t)(int);
+#endif
+
+static sighandler_t saved_sighandler[_NSIG];
+
+/*
+ * Set up the descriptors. Because they are close-on-exec, in the case
+ * where sshd's re-exec fails notify_pipe will still point to a descriptor
+ * that was closed by the exec attempt but if that descriptor has been
+ * reopened then we'll attempt to use that. Ensure that notify_pipe is
+ * outside of the range used by sshd re-exec but within NFDBITS (so we don't
+ * need to expand the fd_sets).
+ */
+#define REEXEC_MIN_FREE_FD (STDERR_FILENO + 4)
+static int
+pselect_notify_setup_fd(int *fd)
+{
+ int r;
+
+ if ((r = fcntl(*fd, F_DUPFD, REEXEC_MIN_FREE_FD)) < 0 ||
+ fcntl(r, F_SETFD, FD_CLOEXEC) < 0 || r >= FD_SETSIZE)
+ return -1;
+ (void)close(*fd);
+ return (*fd = r);
+}
+
+/*
+ * we write to this pipe if a SIGCHLD is caught in order to avoid
+ * the race between select() and child_terminated
+ */
+static pid_t notify_pid;
+static int notify_pipe[2];
+static void
+pselect_notify_setup(void)
+{
+ static int initialized;
+
+ if (initialized && notify_pid == getpid())
+ return;
+ if (notify_pid == 0)
+ debug3_f("initializing");
+ else {
+ debug3_f("pid changed, reinitializing");
+ if (notify_pipe[0] != -1)
+ close(notify_pipe[0]);
+ if (notify_pipe[1] != -1)
+ close(notify_pipe[1]);
+ }
+ if (pipe(notify_pipe) == -1) {
+ error("pipe(notify_pipe) failed %s", strerror(errno));
+ } else if (pselect_notify_setup_fd(&notify_pipe[0]) == -1 ||
+ pselect_notify_setup_fd(&notify_pipe[1]) == -1) {
+ error("fcntl(notify_pipe, ...) failed %s", strerror(errno));
+ close(notify_pipe[0]);
+ close(notify_pipe[1]);
+ } else {
+ set_nonblock(notify_pipe[0]);
+ set_nonblock(notify_pipe[1]);
+ notify_pid = getpid();
+ debug3_f("pid %d saved %d pipe0 %d pipe1 %d", getpid(),
+ notify_pid, notify_pipe[0], notify_pipe[1]);
+ initialized = 1;
+ return;
+ }
+ notify_pipe[0] = -1; /* read end */
+ notify_pipe[1] = -1; /* write end */
+}
+static void
+pselect_notify_parent(void)
+{
+ if (notify_pipe[1] != -1)
+ (void)write(notify_pipe[1], "", 1);
+}
+static void
+pselect_notify_prepare(fd_set *readset)
+{
+ if (notify_pipe[0] != -1)
+ FD_SET(notify_pipe[0], readset);
+}
+static void
+pselect_notify_done(fd_set *readset)
+{
+ char c;
+
+ if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset)) {
+ while (read(notify_pipe[0], &c, 1) != -1)
+ debug2_f("reading");
+ FD_CLR(notify_pipe[0], readset);
+ }
+}
+
+/*ARGSUSED*/
+static void
+pselect_sig_handler(int sig)
+{
+ int save_errno = errno;
+
+ pselect_notify_parent();
+ if (saved_sighandler[sig] != NULL)
+ (*saved_sighandler[sig])(sig); /* call original handler */
+ errno = save_errno;
+}
+
+/*
+ * A minimal implementation of pselect(2), built on top of select(2).
+ */
+
+int
+pselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ const struct timespec *timeout, const sigset_t *mask)
+{
+ int ret, sig, saved_errno, unmasked = 0;
+ sigset_t osig;
+ struct sigaction sa, osa;
+ struct timeval tv, *tvp = NULL;
+
+ if (timeout != NULL) {
+ tv.tv_sec = timeout->tv_sec;
+ tv.tv_usec = timeout->tv_nsec / 1000;
+ tvp = &tv;
+ }
+ if (mask == NULL) /* no signal mask, just call select */
+ return select(nfds, readfds, writefds, exceptfds, tvp);
+
+ /* For each signal we're unmasking, install our handler if needed. */
+ for (sig = 0; sig < _NSIG; sig++) {
+ if (sig == SIGKILL || sig == SIGSTOP || sigismember(mask, sig))
+ continue;
+ if (sigaction(sig, NULL, &sa) == 0 &&
+ sa.sa_handler != SIG_IGN && sa.sa_handler != SIG_DFL) {
+ unmasked = 1;
+ if (sa.sa_handler == pselect_sig_handler)
+ continue;
+ sa.sa_handler = pselect_sig_handler;
+ if (sigaction(sig, &sa, &osa) == 0) {
+ debug3_f("installing signal handler for %s, "
+ "previous %p", strsignal(sig),
+ osa.sa_handler);
+ saved_sighandler[sig] = osa.sa_handler;
+ }
+ }
+ }
+ if (unmasked) {
+ pselect_notify_setup();
+ pselect_notify_prepare(readfds);
+ nfds = MAX(nfds, notify_pipe[0] + 1);
+ }
+
+ /* Unmask signals, call select then restore signal mask. */
+ sigprocmask(SIG_SETMASK, mask, &osig);
+ ret = select(nfds, readfds, writefds, exceptfds, tvp);
+ saved_errno = errno;
+ sigprocmask(SIG_SETMASK, &osig, NULL);
+
+ if (unmasked)
+ pselect_notify_done(readfds);
+ errno = saved_errno;
+ return ret;
+}
+#endif
diff --git a/openbsd-compat/bsd-snprintf.c b/openbsd-compat/bsd-snprintf.c
index f041121fd..b9eaee14f 100644
--- a/openbsd-compat/bsd-snprintf.c
+++ b/openbsd-compat/bsd-snprintf.c
@@ -135,13 +135,13 @@
#define DP_S_DONE 7
/* format flags - Bits */
-#define DP_F_MINUS (1 << 0)
-#define DP_F_PLUS (1 << 1)
-#define DP_F_SPACE (1 << 2)
-#define DP_F_NUM (1 << 3)
-#define DP_F_ZERO (1 << 4)
-#define DP_F_UP (1 << 5)
-#define DP_F_UNSIGNED (1 << 6)
+#define DP_F_MINUS (1 << 0)
+#define DP_F_PLUS (1 << 1)
+#define DP_F_SPACE (1 << 2)
+#define DP_F_NUM (1 << 3)
+#define DP_F_ZERO (1 << 4)
+#define DP_F_UP (1 << 5)
+#define DP_F_UNSIGNED (1 << 6)
/* Conversion Flags */
#define DP_C_SHORT 1
@@ -592,7 +592,7 @@ fmtint(char *buffer, size_t *currlen, size_t maxlen,
#ifdef DEBUG_SNPRINTF
printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
- zpadlen, spadlen, min, max, place);
+ zpadlen, spadlen, min, max, place);
#endif
/* Spaces */
diff --git a/openbsd-compat/bsd-waitpid.h b/openbsd-compat/bsd-waitpid.h
index b551268ab..bd61b6909 100644
--- a/openbsd-compat/bsd-waitpid.h
+++ b/openbsd-compat/bsd-waitpid.h
@@ -40,7 +40,7 @@
#define WEXITSTATUS(w) (int)(WIFEXITED(w) ? ((_W_INT(w) >> 8) & 0377) : -1)
#define WTERMSIG(w) (int)(WIFSIGNALED(w) ? (_W_INT(w) & 0177) : -1)
#define WCOREFLAG 0x80
-#define WCOREDUMP(w) ((_W_INT(w)) & WCOREFLAG)
+#define WCOREDUMP(w) ((_W_INT(w)) & WCOREFLAG)
/* Prototype */
pid_t waitpid(int, int *, int);
diff --git a/openbsd-compat/explicit_bzero.c b/openbsd-compat/explicit_bzero.c
index 7a2fa3548..4ffc6553a 100644
--- a/openbsd-compat/explicit_bzero.c
+++ b/openbsd-compat/explicit_bzero.c
@@ -15,7 +15,15 @@
#ifndef HAVE_EXPLICIT_BZERO
-#ifdef HAVE_MEMSET_S
+#ifdef HAVE_EXPLICIT_MEMSET
+
+void
+explicit_bzero(void *p, size_t n)
+{
+ (void)explicit_memset(p, 0, n);
+}
+
+#elif defined(HAVE_MEMSET_S)
void
explicit_bzero(void *p, size_t n)
diff --git a/openbsd-compat/getopt_long.c b/openbsd-compat/getopt_long.c
index e28947430..1a5001f7d 100644
--- a/openbsd-compat/getopt_long.c
+++ b/openbsd-compat/getopt_long.c
@@ -87,7 +87,7 @@ char *optarg; /* argument associated with option */
/* return values */
#define BADCH (int)'?'
#define BADARG ((*options == ':') ? (int)':' : (int)'?')
-#define INORDER (int)1
+#define INORDER (int)1
#define EMSG ""
diff --git a/openbsd-compat/libressl-api-compat.c b/openbsd-compat/libressl-api-compat.c
index fdadd4e59..4d30322f9 100644
--- a/openbsd-compat/libressl-api-compat.c
+++ b/openbsd-compat/libressl-api-compat.c
@@ -284,7 +284,7 @@ RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
if ((r->dmp1 == NULL && dmp1 == NULL) ||
(r->dmq1 == NULL && dmq1 == NULL) ||
(r->iqmp == NULL && iqmp == NULL))
- return 0;
+ return 0;
if (dmp1 != NULL) {
BN_free(r->dmp1);
diff --git a/openbsd-compat/memmem.c b/openbsd-compat/memmem.c
index 3e5e6b5e6..2637401d7 100644
--- a/openbsd-compat/memmem.c
+++ b/openbsd-compat/memmem.c
@@ -1,69 +1,196 @@
-/* $OpenBSD: memmem.c,v 1.4 2015/08/31 02:53:57 guenther Exp $ */
-/*-
- * Copyright (c) 2005 Pascal Gloor <pascal.gloor@spale.com>
+/* $OpenBSD: memmem.c,v 1.5 2020/04/16 12:39:28 claudio Exp $ */
+
+/*
+ * Copyright (c) 2005-2020 Rich Felker, et al.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+/* OPENBSD ORIGINAL: lib/libc/string/memmem.c */
+
#include "includes.h"
#ifndef HAVE_MEMMEM
#include <string.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+static char *
+twobyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
+{
+ uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1];
+ for (h+=2, k-=2; k; k--, hw = hw<<8 | *h++)
+ if (hw == nw) return (char *)h-2;
+ return hw == nw ? (char *)h-2 : 0;
+}
+
+static char *
+threebyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
+{
+ uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8;
+ uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8;
+ for (h+=3, k-=3; k; k--, hw = (hw|*h++)<<8)
+ if (hw == nw) return (char *)h-3;
+ return hw == nw ? (char *)h-3 : 0;
+}
+
+static char *
+fourbyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
+{
+ uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
+ uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
+ for (h+=4, k-=4; k; k--, hw = hw<<8 | *h++)
+ if (hw == nw) return (char *)h-4;
+ return hw == nw ? (char *)h-4 : 0;
+}
+
+#if 0
+/* In -portable, defines.h ensures that these are already defined. */
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+
+#define BITOP(a,b,op) \
+ ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
/*
- * Find the first occurrence of the byte string s in byte string l.
+ * Maxime Crochemore and Dominique Perrin, Two-way string-matching,
+ * Journal of the ACM, 38(3):651-675, July 1991.
*/
-
-void *
-memmem(const void *l, size_t l_len, const void *s, size_t s_len)
+static char *
+twoway_memmem(const unsigned char *h, const unsigned char *z,
+ const unsigned char *n, size_t l)
{
- const char *cur, *last;
- const char *cl = l;
- const char *cs = s;
+ size_t i, ip, jp, k, p, ms, p0, mem, mem0;
+ size_t byteset[32 / sizeof(size_t)] = { 0 };
+ size_t shift[256];
+
+ /* Computing length of needle and fill shift table */
+ for (i=0; i<l; i++)
+ BITOP(byteset, n[i], |=), shift[n[i]] = i+1;
+
+ /* Compute maximal suffix */
+ ip = -1; jp = 0; k = p = 1;
+ while (jp+k<l) {
+ if (n[ip+k] == n[jp+k]) {
+ if (k == p) {
+ jp += p;
+ k = 1;
+ } else k++;
+ } else if (n[ip+k] > n[jp+k]) {
+ jp += k;
+ k = 1;
+ p = jp - ip;
+ } else {
+ ip = jp++;
+ k = p = 1;
+ }
+ }
+ ms = ip;
+ p0 = p;
+
+ /* And with the opposite comparison */
+ ip = -1; jp = 0; k = p = 1;
+ while (jp+k<l) {
+ if (n[ip+k] == n[jp+k]) {
+ if (k == p) {
+ jp += p;
+ k = 1;
+ } else k++;
+ } else if (n[ip+k] < n[jp+k]) {
+ jp += k;
+ k = 1;
+ p = jp - ip;
+ } else {
+ ip = jp++;
+ k = p = 1;
+ }
+ }
+ if (ip+1 > ms+1) ms = ip;
+ else p = p0;
- /* a zero length needle should just return the haystack */
- if (s_len == 0)
- return (void *)cl;
+ /* Periodic needle? */
+ if (memcmp(n, n+p, ms+1)) {
+ mem0 = 0;
+ p = MAX(ms, l-ms-1) + 1;
+ } else mem0 = l-p;
+ mem = 0;
- /* "s" must be smaller or equal to "l" */
- if (l_len < s_len)
- return NULL;
+ /* Search loop */
+ for (;;) {
+ /* If remainder of haystack is shorter than needle, done */
+ if (z-h < l) return 0;
+
+ /* Check last byte first; advance by shift on mismatch */
+ if (BITOP(byteset, h[l-1], &)) {
+ k = l-shift[h[l-1]];
+ if (k) {
+ if (k < mem) k = mem;
+ h += k;
+ mem = 0;
+ continue;
+ }
+ } else {
+ h += l;
+ mem = 0;
+ continue;
+ }
+
+ /* Compare right half */
+ for (k=MAX(ms+1,mem); k<l && n[k] == h[k]; k++);
+ if (k < l) {
+ h += k-ms;
+ mem = 0;
+ continue;
+ }
+ /* Compare left half */
+ for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
+ if (k <= mem) return (char *)h;
+ h += p;
+ mem = mem0;
+ }
+}
+
+void *
+memmem(const void *h0, size_t k, const void *n0, size_t l)
+{
+ const unsigned char *h = h0, *n = n0;
- /* special case where s_len == 1 */
- if (s_len == 1)
- return memchr(l, *cs, l_len);
+ /* Return immediately on empty needle */
+ if (!l) return (void *)h;
- /* the last position where its possible to find "s" in "l" */
- last = cl + l_len - s_len;
+ /* Return immediately when needle is longer than haystack */
+ if (k<l) return 0;
- for (cur = cl; cur <= last; cur++)
- if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
- return (void *)cur;
+ /* Use faster algorithms for short needles */
+ h = memchr(h0, *n, k);
+ if (!h || l==1) return (void *)h;
+ k -= h - (const unsigned char *)h0;
+ if (k<l) return 0;
+ if (l==2) return twobyte_memmem(h, k, n);
+ if (l==3) return threebyte_memmem(h, k, n);
+ if (l==4) return fourbyte_memmem(h, k, n);
- return NULL;
+ return twoway_memmem(h, h+k, n, l);
}
DEF_WEAK(memmem);
#endif /* HAVE_MEMMEM */
diff --git a/openbsd-compat/mktemp.c b/openbsd-compat/mktemp.c
index 4eb52f421..ac922c1ec 100644
--- a/openbsd-compat/mktemp.c
+++ b/openbsd-compat/mktemp.c
@@ -34,7 +34,7 @@
#include <ctype.h>
#include <unistd.h>
-#if !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP)
+#if !defined(HAVE_MKDTEMP)
#define MKTEMP_NAME 0
#define MKTEMP_FILE 1
@@ -138,4 +138,4 @@ mkdtemp(char *path)
return(error ? NULL : path);
}
-#endif /* !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP) */
+#endif /* !defined(HAVE_MKDTEMP) */
diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h
index e5fd6f5bb..a7209ceb2 100644
--- a/openbsd-compat/openbsd-compat.h
+++ b/openbsd-compat/openbsd-compat.h
@@ -48,6 +48,11 @@
#include "blf.h"
#include "fnmatch.h"
+#if defined(HAVE_LOGIN_CAP) && !defined(HAVE_LOGIN_GETPWCLASS)
+# include <login_cap.h>
+# define login_getpwclass(pw) login_getclass(pw->pw_class)
+#endif
+
#ifndef HAVE_BASENAME
char *basename(const char *path);
#endif
@@ -122,7 +127,7 @@ void strmode(int mode, char *p);
char *strptime(const char *buf, const char *fmt, struct tm *tm);
#endif
-#if !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP)
+#if !defined(HAVE_MKDTEMP)
int mkstemps(char *path, int slen);
int mkstemp(char *path);
char *mkdtemp(char *path);
@@ -190,9 +195,9 @@ int writev(int, struct iovec *, int);
#endif
/* Home grown routines */
+#include "bsd-signal.h"
#include "bsd-misc.h"
#include "bsd-setres_id.h"
-#include "bsd-signal.h"
#include "bsd-statvfs.h"
#include "bsd-waitpid.h"
#include "bsd-poll.h"
diff --git a/openbsd-compat/openssl-compat.h b/openbsd-compat/openssl-compat.h
index 388ae8aa0..8ca50b5ac 100644
--- a/openbsd-compat/openssl-compat.h
+++ b/openbsd-compat/openssl-compat.h
@@ -113,8 +113,12 @@ int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key);
#endif /* HAVE_DSA_SET0_KEY */
#ifndef HAVE_EVP_CIPHER_CTX_GET_IV
+# ifdef HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV
+# define EVP_CIPHER_CTX_get_iv EVP_CIPHER_CTX_get_updated_iv
+# else /* HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV */
int EVP_CIPHER_CTX_get_iv(const EVP_CIPHER_CTX *ctx,
unsigned char *iv, size_t len);
+# endif /* HAVE_EVP_CIPHER_CTX_GET_UPDATED_IV */
#endif /* HAVE_EVP_CIPHER_CTX_GET_IV */
#ifndef HAVE_EVP_CIPHER_CTX_SET_IV
diff --git a/openbsd-compat/port-aix.c b/openbsd-compat/port-aix.c
index e0d3eba51..2ac9bad09 100644
--- a/openbsd-compat/port-aix.c
+++ b/openbsd-compat/port-aix.c
@@ -445,7 +445,7 @@ getgrouplist(const char *user, gid_t pgid, gid_t *groups, int *grpcnt)
char *cp, *grplist, *grp;
gid_t gid;
int ret = 0, ngroups = 0, maxgroups;
- long l;
+ long long ll;
maxgroups = *grpcnt;
@@ -463,12 +463,12 @@ getgrouplist(const char *user, gid_t pgid, gid_t *groups, int *grpcnt)
/* copy each entry from getgrset into group list */
while ((grp = strsep(&grplist, ",")) != NULL) {
- l = strtol(grp, NULL, 10);
- if (ngroups >= maxgroups || l == LONG_MIN || l == LONG_MAX) {
+ ll = strtoll(grp, NULL, 10);
+ if (ngroups >= maxgroups || ll < 0 || ll > UID_MAX) {
ret = -1;
goto out;
}
- gid = (gid_t)l;
+ gid = (gid_t)ll;
if (gid == pgid)
continue; /* we have already added primary gid */
groups[ngroups++] = gid;
diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c
index f46094faf..77cb8213a 100644
--- a/openbsd-compat/port-linux.c
+++ b/openbsd-compat/port-linux.c
@@ -55,11 +55,10 @@ ssh_selinux_enabled(void)
}
/* Return the default security context for the given username */
-static security_context_t
+static char *
ssh_selinux_getctxbyname(char *pwname)
{
- security_context_t sc = NULL;
- char *sename = NULL, *lvl = NULL;
+ char *sc = NULL, *sename = NULL, *lvl = NULL;
int r;
#ifdef HAVE_GETSEUSERBYNAME
@@ -105,7 +104,7 @@ ssh_selinux_getctxbyname(char *pwname)
void
ssh_selinux_setup_exec_context(char *pwname)
{
- security_context_t user_ctx = NULL;
+ char *user_ctx = NULL;
if (!ssh_selinux_enabled())
return;
@@ -136,9 +135,7 @@ ssh_selinux_setup_exec_context(char *pwname)
void
ssh_selinux_setup_pty(char *pwname, const char *tty)
{
- security_context_t new_tty_ctx = NULL;
- security_context_t user_ctx = NULL;
- security_context_t old_tty_ctx = NULL;
+ char *new_tty_ctx = NULL, *user_ctx = NULL, *old_tty_ctx = NULL;
security_class_t chrclass;
if (!ssh_selinux_enabled())
@@ -182,18 +179,18 @@ ssh_selinux_change_context(const char *newname)
{
int len, newlen;
char *oldctx, *newctx, *cx;
- void (*switchlog) (const char *fmt,...) = logit;
+ LogLevel log_level = SYSLOG_LEVEL_INFO;
if (!ssh_selinux_enabled())
return;
- if (getcon((security_context_t *)&oldctx) < 0) {
+ if (getcon(&oldctx) < 0) {
logit("%s: getcon failed with %s", __func__, strerror(errno));
return;
}
if ((cx = index(oldctx, ':')) == NULL || (cx = index(cx + 1, ':')) ==
NULL) {
- logit ("%s: unparsable context %s", __func__, oldctx);
+ logit("%s: unparsable context %s", __func__, oldctx);
return;
}
@@ -203,7 +200,7 @@ ssh_selinux_change_context(const char *newname)
*/
if (strncmp(cx, SSH_SELINUX_UNCONFINED_TYPE,
sizeof(SSH_SELINUX_UNCONFINED_TYPE) - 1) == 0)
- switchlog = debug3;
+ log_level = SYSLOG_LEVEL_DEBUG3;
newlen = strlen(oldctx) + strlen(newname) + 1;
newctx = xmalloc(newlen);
@@ -215,8 +212,8 @@ ssh_selinux_change_context(const char *newname)
debug3("%s: setting context from '%s' to '%s'", __func__,
oldctx, newctx);
if (setcon(newctx) < 0)
- switchlog("%s: setcon %s from %s failed with %s", __func__,
- newctx, oldctx, strerror(errno));
+ do_log2(log_level, "%s: setcon %s from %s failed with %s",
+ __func__, newctx, oldctx, strerror(errno));
free(oldctx);
free(newctx);
}
@@ -224,7 +221,7 @@ ssh_selinux_change_context(const char *newname)
void
ssh_selinux_setfscreatecon(const char *path)
{
- security_context_t context;
+ char *context;
if (!ssh_selinux_enabled())
return;
diff --git a/openbsd-compat/port-net.c b/openbsd-compat/port-net.c
index 617bffceb..198e73f0d 100644
--- a/openbsd-compat/port-net.c
+++ b/openbsd-compat/port-net.c
@@ -26,6 +26,7 @@
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
+#include <stdio.h>
#include <string.h>
#include <unistd.h>
@@ -67,7 +68,7 @@ sys_set_rdomain(int fd, const char *name)
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
name, strlen(name)) == -1) {
error("%s: setsockopt(%d, SO_BINDTODEVICE, %s): %s",
- __func__, fd, name, strerror(errno));
+ __func__, fd, name, strerror(errno));
return -1;
}
return 0;
@@ -209,8 +210,11 @@ sys_tun_open(int tun, int mode, char **ifname)
{
struct ifreq ifr;
char name[100];
- int fd = -1, sock, flag;
+ int fd = -1, sock;
const char *tunbase = "tun";
+#if defined(TUNSIFHEAD) && !defined(SSH_TUN_PREPEND_AF)
+ int flag;
+#endif
if (ifname != NULL)
*ifname = NULL;
@@ -247,8 +251,8 @@ sys_tun_open(int tun, int mode, char **ifname)
}
/* Turn on tunnel headers */
- flag = 1;
#if defined(TUNSIFHEAD) && !defined(SSH_TUN_PREPEND_AF)
+ flag = 1;
if (mode != SSH_TUNMODE_ETHERNET &&
ioctl(fd, TUNSIFHEAD, &flag) == -1) {
debug("%s: ioctl(%d, TUNSIFHEAD, 1): %s", __func__, fd,
diff --git a/openbsd-compat/port-prngd.c b/openbsd-compat/port-prngd.c
new file mode 100644
index 000000000..6afa8f913
--- /dev/null
+++ b/openbsd-compat/port-prngd.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2001 Damien Miller. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_UN_H
+# include <sys/un.h>
+#endif
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stddef.h> /* for offsetof */
+
+#include "atomicio.h"
+#include "misc.h"
+#include "log.h"
+
+#if defined(PRNGD_PORT) || defined(PRNGD_SOCKET)
+/*
+ * EGD/PRNGD interface.
+ *
+ * Collect 'len' bytes of entropy into 'buf' from PRNGD/EGD daemon
+ * listening either on 'tcp_port', or via Unix domain socket at *
+ * 'socket_path'.
+ * Either a non-zero tcp_port or a non-null socket_path must be
+ * supplied.
+ * Returns 0 on success, -1 on error
+ */
+static int
+get_random_bytes_prngd(unsigned char *buf, int len,
+ unsigned short tcp_port, char *socket_path)
+{
+ int fd, addr_len, rval, errors;
+ u_char msg[2];
+ struct sockaddr_storage addr;
+ struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
+ struct sockaddr_un *addr_un = (struct sockaddr_un *)&addr;
+ sshsig_t old_sigpipe;
+
+ /* Sanity checks */
+ if (socket_path == NULL && tcp_port == 0)
+ fatal("You must specify a port or a socket");
+ if (socket_path != NULL &&
+ strlen(socket_path) >= sizeof(addr_un->sun_path))
+ fatal("Random pool path is too long");
+ if (len <= 0 || len > 255)
+ fatal("Too many bytes (%d) to read from PRNGD", len);
+
+ memset(&addr, '\0', sizeof(addr));
+
+ if (tcp_port != 0) {
+ addr_in->sin_family = AF_INET;
+ addr_in->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addr_in->sin_port = htons(tcp_port);
+ addr_len = sizeof(*addr_in);
+ } else {
+ addr_un->sun_family = AF_UNIX;
+ strlcpy(addr_un->sun_path, socket_path,
+ sizeof(addr_un->sun_path));
+ addr_len = offsetof(struct sockaddr_un, sun_path) +
+ strlen(socket_path) + 1;
+ }
+
+ old_sigpipe = ssh_signal(SIGPIPE, SIG_IGN);
+
+ errors = 0;
+ rval = -1;
+reopen:
+ fd = socket(addr.ss_family, SOCK_STREAM, 0);
+ if (fd == -1) {
+ error("Couldn't create socket: %s", strerror(errno));
+ goto done;
+ }
+
+ if (connect(fd, (struct sockaddr*)&addr, addr_len) == -1) {
+ if (tcp_port != 0) {
+ error("Couldn't connect to PRNGD port %d: %s",
+ tcp_port, strerror(errno));
+ } else {
+ error("Couldn't connect to PRNGD socket \"%s\": %s",
+ addr_un->sun_path, strerror(errno));
+ }
+ goto done;
+ }
+
+ /* Send blocking read request to PRNGD */
+ msg[0] = 0x02;
+ msg[1] = len;
+
+ if (atomicio(vwrite, fd, msg, sizeof(msg)) != sizeof(msg)) {
+ if (errno == EPIPE && errors < 10) {
+ close(fd);
+ errors++;
+ goto reopen;
+ }
+ error("Couldn't write to PRNGD socket: %s",
+ strerror(errno));
+ goto done;
+ }
+
+ if (atomicio(read, fd, buf, len) != (size_t)len) {
+ if (errno == EPIPE && errors < 10) {
+ close(fd);
+ errors++;
+ goto reopen;
+ }
+ error("Couldn't read from PRNGD socket: %s",
+ strerror(errno));
+ goto done;
+ }
+
+ rval = 0;
+done:
+ ssh_signal(SIGPIPE, old_sigpipe);
+ if (fd != -1)
+ close(fd);
+ return rval;
+}
+#endif /* PRNGD_PORT || PRNGD_SOCKET */
+
+int
+seed_from_prngd(unsigned char *buf, size_t bytes)
+{
+#ifdef PRNGD_PORT
+ debug("trying egd/prngd port %d", PRNGD_PORT);
+ if (get_random_bytes_prngd(buf, bytes, PRNGD_PORT, NULL) == 0)
+ return 0;
+#endif
+#ifdef PRNGD_SOCKET
+ debug("trying egd/prngd socket %s", PRNGD_SOCKET);
+ if (get_random_bytes_prngd(buf, bytes, 0, PRNGD_SOCKET) == 0)
+ return 0;
+#endif
+ return -1;
+}
diff --git a/openbsd-compat/port-solaris.c b/openbsd-compat/port-solaris.c
index 7d5a28cd0..b84fbff5e 100644
--- a/openbsd-compat/port-solaris.c
+++ b/openbsd-compat/port-solaris.c
@@ -17,8 +17,6 @@
#include "config.h"
#include "includes.h"
-#ifdef USE_SOLARIS_PROCESS_CONTRACTS
-
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
@@ -31,12 +29,14 @@
#include <string.h>
#include <unistd.h>
+#include "log.h"
+
+#ifdef USE_SOLARIS_PROCESS_CONTRACTS
+
#include <libcontract.h>
#include <sys/contract/process.h>
#include <sys/ctfs.h>
-#include "log.h"
-
#define CT_TEMPLATE CTFS_ROOT "/process/template"
#define CT_LATEST CTFS_ROOT "/process/latest"
diff --git a/openbsd-compat/port-uw.c b/openbsd-compat/port-uw.c
index 132213131..074f80c8d 100644
--- a/openbsd-compat/port-uw.c
+++ b/openbsd-compat/port-uw.c
@@ -143,7 +143,7 @@ get_iaf_password(struct passwd *pw)
if (pw_password == NULL)
fatal("ia_get_logpwd: Unable to get the shadow passwd");
ia_closeinfo(uinfo);
- return pw_password;
+ return pw_password;
}
else
fatal("ia_openinfo: Unable to open the shadow passwd file");
diff --git a/openbsd-compat/regress/Makefile.in b/openbsd-compat/regress/Makefile.in
index c5aae61e2..dd8cdc4b7 100644
--- a/openbsd-compat/regress/Makefile.in
+++ b/openbsd-compat/regress/Makefile.in
@@ -7,7 +7,7 @@ VPATH=@srcdir@
CC=@CC@
LD=@LD@
CFLAGS=@CFLAGS@
-CPPFLAGS=-I. -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@
+CPPFLAGS=-I. -I.. -I../.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../.. @CPPFLAGS@ @DEFS@
EXEEXT=@EXEEXT@
LIBCOMPAT=../libopenbsd-compat.a
LIBS=@LIBS@
diff --git a/openbsd-compat/regress/closefromtest.c b/openbsd-compat/regress/closefromtest.c
index 82ffeb9a7..7a69fb2b1 100644
--- a/openbsd-compat/regress/closefromtest.c
+++ b/openbsd-compat/regress/closefromtest.c
@@ -14,6 +14,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/stat.h>
@@ -24,8 +26,6 @@
#define NUM_OPENS 10
-int closefrom(int);
-
void
fail(char *msg)
{
diff --git a/openbsd-compat/regress/opensslvertest.c b/openbsd-compat/regress/opensslvertest.c
index 5d019b598..43825b24c 100644
--- a/openbsd-compat/regress/opensslvertest.c
+++ b/openbsd-compat/regress/opensslvertest.c
@@ -14,6 +14,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <stdio.h>
#include <stdlib.h>
diff --git a/openbsd-compat/regress/snprintftest.c b/openbsd-compat/regress/snprintftest.c
index 6dc2e222a..a3134db1c 100644
--- a/openbsd-compat/regress/snprintftest.c
+++ b/openbsd-compat/regress/snprintftest.c
@@ -17,6 +17,8 @@
#define BUFSZ 2048
+#include "includes.h"
+
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
diff --git a/openbsd-compat/regress/strduptest.c b/openbsd-compat/regress/strduptest.c
index 7f6d779be..8a3ccf771 100644
--- a/openbsd-compat/regress/strduptest.c
+++ b/openbsd-compat/regress/strduptest.c
@@ -14,6 +14,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <stdlib.h>
#include <string.h>
diff --git a/openbsd-compat/regress/strtonumtest.c b/openbsd-compat/regress/strtonumtest.c
index 50ca5bd22..46bd2b916 100644
--- a/openbsd-compat/regress/strtonumtest.c
+++ b/openbsd-compat/regress/strtonumtest.c
@@ -17,6 +17,8 @@
/* OPENBSD ORIGINAL: regress/lib/libc/strtonum/strtonumtest.c */
+#include "includes.h"
+
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/openbsd-compat/regress/utimensattest.c b/openbsd-compat/regress/utimensattest.c
index 24312e5d8..bbc66c485 100644
--- a/openbsd-compat/regress/utimensattest.c
+++ b/openbsd-compat/regress/utimensattest.c
@@ -14,6 +14,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/stat.h>
diff --git a/openbsd-compat/setenv.c b/openbsd-compat/setenv.c
index 373b701d9..86954c284 100644
--- a/openbsd-compat/setenv.c
+++ b/openbsd-compat/setenv.c
@@ -39,7 +39,9 @@
#include <string.h>
extern char **environ;
+#ifndef HAVE_SETENV
static char **lastenv; /* last value of environ */
+#endif
/* OpenSSH Portable: __findenv is from getenv.c rev 1.8, made static */
/*
diff --git a/openbsd-compat/sha2.c b/openbsd-compat/sha2.c
index e36cc24ef..4f2ad8f23 100644
--- a/openbsd-compat/sha2.c
+++ b/openbsd-compat/sha2.c
@@ -45,7 +45,7 @@
#define MAKE_CLONE(x, y) void __ssh_compat_make_clone_##x_##y(void)
#include <string.h>
-#include <sha2.h>
+#include "openbsd-compat/sha2.h"
/*
* UNROLLED TRANSFORM LOOP NOTE:
@@ -159,7 +159,7 @@
* same "backwards" definition.
*/
/* Shift-right (used in SHA-224, SHA-256, SHA-384, and SHA-512): */
-#define R(b,x) ((x) >> (b))
+#define R(b,x) ((x) >> (b))
/* 32-bit Rotate-right (used in SHA-224 and SHA-256): */
#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b))))
/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
diff --git a/openbsd-compat/strtonum.c b/openbsd-compat/strtonum.c
index 87f2f24b2..130d89684 100644
--- a/openbsd-compat/strtonum.c
+++ b/openbsd-compat/strtonum.c
@@ -26,9 +26,9 @@
#include <limits.h>
#include <errno.h>
-#define INVALID 1
-#define TOOSMALL 2
-#define TOOLARGE 3
+#define INVALID 1
+#define TOOSMALL 2
+#define TOOLARGE 3
long long
strtonum(const char *numstr, long long minval, long long maxval,
diff --git a/openbsd-compat/sys-queue.h b/openbsd-compat/sys-queue.h
index 5108f394c..816c15cd4 100644
--- a/openbsd-compat/sys-queue.h
+++ b/openbsd-compat/sys-queue.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: queue.h,v 1.36 2012/04/11 13:29:14 naddy Exp $ */
+/* $OpenBSD: queue.h,v 1.45 2018/07/12 14:22:54 sashan Exp $ */
/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
/*
@@ -41,94 +41,97 @@
* Require for OS/X and other platforms that have old/broken/incomplete
* <sys/queue.h>.
*/
-#undef SLIST_HEAD
-#undef SLIST_HEAD_INITIALIZER
-#undef SLIST_ENTRY
-#undef SLIST_FOREACH_PREVPTR
-#undef SLIST_FOREACH_SAFE
-#undef SLIST_FIRST
-#undef SLIST_END
-#undef SLIST_EMPTY
-#undef SLIST_NEXT
-#undef SLIST_FOREACH
-#undef SLIST_INIT
-#undef SLIST_INSERT_AFTER
-#undef SLIST_INSERT_HEAD
-#undef SLIST_REMOVE_HEAD
-#undef SLIST_REMOVE_AFTER
-#undef SLIST_REMOVE
-#undef SLIST_REMOVE_NEXT
-#undef LIST_HEAD
-#undef LIST_HEAD_INITIALIZER
+#undef CIRCLEQ_EMPTY
+#undef CIRCLEQ_END
+#undef CIRCLEQ_ENTRY
+#undef CIRCLEQ_FIRST
+#undef CIRCLEQ_FOREACH
+#undef CIRCLEQ_FOREACH_REVERSE
+#undef CIRCLEQ_HEAD
+#undef CIRCLEQ_HEAD_INITIALIZER
+#undef CIRCLEQ_INIT
+#undef CIRCLEQ_INSERT_AFTER
+#undef CIRCLEQ_INSERT_BEFORE
+#undef CIRCLEQ_INSERT_HEAD
+#undef CIRCLEQ_INSERT_TAIL
+#undef CIRCLEQ_LAST
+#undef CIRCLEQ_NEXT
+#undef CIRCLEQ_PREV
+#undef CIRCLEQ_REMOVE
+#undef CIRCLEQ_REPLACE
+#undef LIST_EMPTY
+#undef LIST_END
#undef LIST_ENTRY
#undef LIST_FIRST
-#undef LIST_END
-#undef LIST_EMPTY
-#undef LIST_NEXT
#undef LIST_FOREACH
#undef LIST_FOREACH_SAFE
+#undef LIST_HEAD
+#undef LIST_HEAD_INITIALIZER
#undef LIST_INIT
#undef LIST_INSERT_AFTER
#undef LIST_INSERT_BEFORE
#undef LIST_INSERT_HEAD
+#undef LIST_NEXT
#undef LIST_REMOVE
#undef LIST_REPLACE
-#undef SIMPLEQ_HEAD
-#undef SIMPLEQ_HEAD_INITIALIZER
+#undef SIMPLEQ_CONCAT
+#undef SIMPLEQ_EMPTY
+#undef SIMPLEQ_END
#undef SIMPLEQ_ENTRY
#undef SIMPLEQ_FIRST
-#undef SIMPLEQ_END
-#undef SIMPLEQ_EMPTY
-#undef SIMPLEQ_NEXT
#undef SIMPLEQ_FOREACH
#undef SIMPLEQ_FOREACH_SAFE
+#undef SIMPLEQ_HEAD
+#undef SIMPLEQ_HEAD_INITIALIZER
#undef SIMPLEQ_INIT
+#undef SIMPLEQ_INSERT_AFTER
#undef SIMPLEQ_INSERT_HEAD
#undef SIMPLEQ_INSERT_TAIL
-#undef SIMPLEQ_INSERT_AFTER
+#undef SIMPLEQ_NEXT
+#undef SIMPLEQ_REMOVE_AFTER
#undef SIMPLEQ_REMOVE_HEAD
-#undef TAILQ_HEAD
-#undef TAILQ_HEAD_INITIALIZER
+#undef SLIST_EMPTY
+#undef SLIST_END
+#undef SLIST_ENTRY
+#undef SLIST_FIRST
+#undef SLIST_FOREACH
+#undef SLIST_FOREACH_PREVPTR
+#undef SLIST_FOREACH_SAFE
+#undef SLIST_HEAD
+#undef SLIST_HEAD_INITIALIZER
+#undef SLIST_INIT
+#undef SLIST_INSERT_AFTER
+#undef SLIST_INSERT_HEAD
+#undef SLIST_NEXT
+#undef SLIST_REMOVE
+#undef SLIST_REMOVE_AFTER
+#undef SLIST_REMOVE_HEAD
+#undef SLIST_REMOVE_NEXT
+#undef TAILQ_CONCAT
+#undef TAILQ_EMPTY
+#undef TAILQ_END
#undef TAILQ_ENTRY
#undef TAILQ_FIRST
-#undef TAILQ_END
-#undef TAILQ_NEXT
-#undef TAILQ_LAST
-#undef TAILQ_PREV
-#undef TAILQ_EMPTY
#undef TAILQ_FOREACH
#undef TAILQ_FOREACH_REVERSE
-#undef TAILQ_FOREACH_SAFE
#undef TAILQ_FOREACH_REVERSE_SAFE
+#undef TAILQ_FOREACH_SAFE
+#undef TAILQ_HEAD
+#undef TAILQ_HEAD_INITIALIZER
#undef TAILQ_INIT
-#undef TAILQ_INSERT_HEAD
-#undef TAILQ_INSERT_TAIL
#undef TAILQ_INSERT_AFTER
#undef TAILQ_INSERT_BEFORE
+#undef TAILQ_INSERT_HEAD
+#undef TAILQ_INSERT_TAIL
+#undef TAILQ_LAST
+#undef TAILQ_NEXT
+#undef TAILQ_PREV
#undef TAILQ_REMOVE
#undef TAILQ_REPLACE
-#undef CIRCLEQ_HEAD
-#undef CIRCLEQ_HEAD_INITIALIZER
-#undef CIRCLEQ_ENTRY
-#undef CIRCLEQ_FIRST
-#undef CIRCLEQ_LAST
-#undef CIRCLEQ_END
-#undef CIRCLEQ_NEXT
-#undef CIRCLEQ_PREV
-#undef CIRCLEQ_EMPTY
-#undef CIRCLEQ_FOREACH
-#undef CIRCLEQ_FOREACH_REVERSE
-#undef CIRCLEQ_INIT
-#undef CIRCLEQ_INSERT_AFTER
-#undef CIRCLEQ_INSERT_BEFORE
-#undef CIRCLEQ_INSERT_HEAD
-#undef CIRCLEQ_INSERT_TAIL
-#undef CIRCLEQ_REMOVE
-#undef CIRCLEQ_REPLACE
/*
- * This file defines five types of data structures: singly-linked lists,
- * lists, simple queues, tail queues, and circular queues.
+ * This file defines five types of data structures: singly-linked lists,
+ * lists, simple queues, tail queues and XOR simple queues.
*
*
* A singly-linked list is headed by a single forward pointer. The elements
@@ -148,7 +151,7 @@
* or after an existing element or at the head of the list. A list
* may only be traversed in the forward direction.
*
- * A simple queue is headed by a pair of pointers, one the head of the
+ * A simple queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are singly
* linked to save space, so elements can only be removed from the
* head of the list. New elements can be added to the list before or after
@@ -162,19 +165,17 @@
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
- * A circle queue is headed by a pair of pointers, one to the head of the
- * list and the other to the tail of the list. The elements are doubly
- * linked so that an arbitrary element can be removed without a need to
- * traverse the list. New elements can be added to the list before or after
- * an existing element, at the head of the list, or at the end of the list.
- * A circle queue may be traversed in either direction, but has a more
- * complex end of list detection.
+ * An XOR simple queue is used in the same way as a regular simple queue.
+ * The difference is that the head structure also includes a "cookie" that
+ * is XOR'd with the queue pointer (first, last or next) to generate the
+ * real pointer value.
*
* For details on the use of these macros, see the queue(3) manual page.
*/
#if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC))
-#define _Q_INVALIDATE(a) (a) = ((void *)-1)
+#define _Q_INVALID ((void *)-1)
+#define _Q_INVALIDATE(a) (a) = _Q_INVALID
#else
#define _Q_INVALIDATE(a)
#endif
@@ -186,15 +187,15 @@
struct name { \
struct type *slh_first; /* first element */ \
}
-
+
#define SLIST_HEAD_INITIALIZER(head) \
{ NULL }
-
+
#define SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
-
+
/*
* Singly-linked List access methods.
*/
@@ -248,8 +249,8 @@ struct { \
curelm = curelm->field.sle_next; \
curelm->field.sle_next = \
curelm->field.sle_next->field.sle_next; \
- _Q_INVALIDATE((elm)->field.sle_next); \
} \
+ _Q_INVALIDATE((elm)->field.sle_next); \
} while (0)
/*
@@ -270,7 +271,7 @@ struct { \
}
/*
- * List access methods
+ * List access methods.
*/
#define LIST_FIRST(head) ((head)->lh_first)
#define LIST_END(head) NULL
@@ -407,6 +408,94 @@ struct { \
(head)->sqh_last = &(elm)->field.sqe_next; \
} while (0)
+#define SIMPLEQ_CONCAT(head1, head2) do { \
+ if (!SIMPLEQ_EMPTY((head2))) { \
+ *(head1)->sqh_last = (head2)->sqh_first; \
+ (head1)->sqh_last = (head2)->sqh_last; \
+ SIMPLEQ_INIT((head2)); \
+ } \
+} while (0)
+
+/*
+ * XOR Simple queue definitions.
+ */
+#define XSIMPLEQ_HEAD(name, type) \
+struct name { \
+ struct type *sqx_first; /* first element */ \
+ struct type **sqx_last; /* addr of last next element */ \
+ unsigned long sqx_cookie; \
+}
+
+#define XSIMPLEQ_ENTRY(type) \
+struct { \
+ struct type *sqx_next; /* next element */ \
+}
+
+/*
+ * XOR Simple queue access methods.
+ */
+#define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \
+ (unsigned long)(ptr)))
+#define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first))
+#define XSIMPLEQ_END(head) NULL
+#define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head))
+#define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next))
+
+
+#define XSIMPLEQ_FOREACH(var, head, field) \
+ for ((var) = XSIMPLEQ_FIRST(head); \
+ (var) != XSIMPLEQ_END(head); \
+ (var) = XSIMPLEQ_NEXT(head, var, field))
+
+#define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = XSIMPLEQ_FIRST(head); \
+ (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \
+ (var) = (tvar))
+
+/*
+ * XOR Simple queue functions.
+ */
+#define XSIMPLEQ_INIT(head) do { \
+ arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \
+ (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
+} while (0)
+
+#define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqx_next = (head)->sqx_first) == \
+ XSIMPLEQ_XOR(head, NULL)) \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
+ (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \
+} while (0)
+
+#define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \
+ *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
+} while (0)
+
+#define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \
+ XSIMPLEQ_XOR(head, NULL)) \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
+ (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \
+} while (0)
+
+#define XSIMPLEQ_REMOVE_HEAD(head, field) do { \
+ if (((head)->sqx_first = XSIMPLEQ_XOR(head, \
+ (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \
+ (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \
+} while (0)
+
+#define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
+ if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \
+ (elm)->field.sqx_next)->field.sqx_next) \
+ == XSIMPLEQ_XOR(head, NULL)) \
+ (head)->sqx_last = \
+ XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \
+} while (0)
+
+
/*
* Tail queue definitions.
*/
@@ -425,8 +514,8 @@ struct { \
struct type **tqe_prev; /* address of previous next element */ \
}
-/*
- * tail queue access methods
+/*
+ * Tail queue access methods.
*/
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_END(head) NULL
@@ -527,133 +616,13 @@ struct { \
_Q_INVALIDATE((elm)->field.tqe_next); \
} while (0)
-/*
- * Circular queue definitions.
- */
-#define CIRCLEQ_HEAD(name, type) \
-struct name { \
- struct type *cqh_first; /* first element */ \
- struct type *cqh_last; /* last element */ \
-}
-
-#define CIRCLEQ_HEAD_INITIALIZER(head) \
- { CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
-
-#define CIRCLEQ_ENTRY(type) \
-struct { \
- struct type *cqe_next; /* next element */ \
- struct type *cqe_prev; /* previous element */ \
-}
-
-/*
- * Circular queue access methods
- */
-#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
-#define CIRCLEQ_LAST(head) ((head)->cqh_last)
-#define CIRCLEQ_END(head) ((void *)(head))
-#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
-#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
-#define CIRCLEQ_EMPTY(head) \
- (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
-
-#define CIRCLEQ_FOREACH(var, head, field) \
- for((var) = CIRCLEQ_FIRST(head); \
- (var) != CIRCLEQ_END(head); \
- (var) = CIRCLEQ_NEXT(var, field))
-
-#define CIRCLEQ_FOREACH_SAFE(var, head, field, tvar) \
- for ((var) = CIRCLEQ_FIRST(head); \
- (var) != CIRCLEQ_END(head) && \
- ((tvar) = CIRCLEQ_NEXT(var, field), 1); \
- (var) = (tvar))
-
-#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
- for((var) = CIRCLEQ_LAST(head); \
- (var) != CIRCLEQ_END(head); \
- (var) = CIRCLEQ_PREV(var, field))
-
-#define CIRCLEQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
- for ((var) = CIRCLEQ_LAST(head, headname); \
- (var) != CIRCLEQ_END(head) && \
- ((tvar) = CIRCLEQ_PREV(var, headname, field), 1); \
- (var) = (tvar))
-
-/*
- * Circular queue functions.
- */
-#define CIRCLEQ_INIT(head) do { \
- (head)->cqh_first = CIRCLEQ_END(head); \
- (head)->cqh_last = CIRCLEQ_END(head); \
-} while (0)
-
-#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
- (elm)->field.cqe_next = (listelm)->field.cqe_next; \
- (elm)->field.cqe_prev = (listelm); \
- if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \
- (head)->cqh_last = (elm); \
- else \
- (listelm)->field.cqe_next->field.cqe_prev = (elm); \
- (listelm)->field.cqe_next = (elm); \
-} while (0)
-
-#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
- (elm)->field.cqe_next = (listelm); \
- (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
- if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \
- (head)->cqh_first = (elm); \
- else \
- (listelm)->field.cqe_prev->field.cqe_next = (elm); \
- (listelm)->field.cqe_prev = (elm); \
-} while (0)
-
-#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
- (elm)->field.cqe_next = (head)->cqh_first; \
- (elm)->field.cqe_prev = CIRCLEQ_END(head); \
- if ((head)->cqh_last == CIRCLEQ_END(head)) \
- (head)->cqh_last = (elm); \
- else \
- (head)->cqh_first->field.cqe_prev = (elm); \
- (head)->cqh_first = (elm); \
-} while (0)
-
-#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
- (elm)->field.cqe_next = CIRCLEQ_END(head); \
- (elm)->field.cqe_prev = (head)->cqh_last; \
- if ((head)->cqh_first == CIRCLEQ_END(head)) \
- (head)->cqh_first = (elm); \
- else \
- (head)->cqh_last->field.cqe_next = (elm); \
- (head)->cqh_last = (elm); \
-} while (0)
-
-#define CIRCLEQ_REMOVE(head, elm, field) do { \
- if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \
- (head)->cqh_last = (elm)->field.cqe_prev; \
- else \
- (elm)->field.cqe_next->field.cqe_prev = \
- (elm)->field.cqe_prev; \
- if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \
- (head)->cqh_first = (elm)->field.cqe_next; \
- else \
- (elm)->field.cqe_prev->field.cqe_next = \
- (elm)->field.cqe_next; \
- _Q_INVALIDATE((elm)->field.cqe_prev); \
- _Q_INVALIDATE((elm)->field.cqe_next); \
-} while (0)
-
-#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
- if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
- CIRCLEQ_END(head)) \
- (head).cqh_last = (elm2); \
- else \
- (elm2)->field.cqe_next->field.cqe_prev = (elm2); \
- if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
- CIRCLEQ_END(head)) \
- (head).cqh_first = (elm2); \
- else \
- (elm2)->field.cqe_prev->field.cqe_next = (elm2); \
- _Q_INVALIDATE((elm)->field.cqe_prev); \
- _Q_INVALIDATE((elm)->field.cqe_next); \
+#define TAILQ_CONCAT(head1, head2, field) do { \
+ if (!TAILQ_EMPTY(head2)) { \
+ *(head1)->tqh_last = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ TAILQ_INIT((head2)); \
+ } \
} while (0)
-#endif /* !_FAKE_QUEUE_H_ */
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/opensshd.init.in b/opensshd.init.in
index 99e5a51ab..251724805 100755
--- a/opensshd.init.in
+++ b/opensshd.init.in
@@ -17,26 +17,6 @@ PIDFILE=$piddir/sshd.pid
PidFile=`grep "^PidFile" ${sysconfdir}/sshd_config | tr "=" " " | awk '{print $2}'`
[ X$PidFile = X ] || PIDFILE=$PidFile
SSH_KEYGEN=$prefix/bin/ssh-keygen
-HOST_KEY_DSA=$sysconfdir/ssh_host_dsa_key
-HOST_KEY_RSA=$sysconfdir/ssh_host_rsa_key
-@COMMENT_OUT_ECC@HOST_KEY_ECDSA=$sysconfdir/ssh_host_ecdsa_key
-HOST_KEY_ED25519=$sysconfdir/ssh_host_ed25519_key
-
-
-checkkeys() {
- if [ ! -f $HOST_KEY_DSA ]; then
- ${SSH_KEYGEN} -t dsa -f ${HOST_KEY_DSA} -N ""
- fi
- if [ ! -f $HOST_KEY_RSA ]; then
- ${SSH_KEYGEN} -t rsa -f ${HOST_KEY_RSA} -N ""
- fi
-@COMMENT_OUT_ECC@ if [ ! -f $HOST_KEY_ECDSA ]; then
-@COMMENT_OUT_ECC@ ${SSH_KEYGEN} -t ecdsa -f ${HOST_KEY_ECDSA} -N ""
-@COMMENT_OUT_ECC@ fi
- if [ ! -f $HOST_KEY_ED25519 ]; then
- ${SSH_KEYGEN} -t ed25519 -f ${HOST_KEY_ED25519} -N ""
- fi
-}
stop_service() {
if [ -r $PIDFILE -a ! -z ${PIDFILE} ]; then
@@ -54,7 +34,7 @@ start_service() {
# XXX we will opt out at this time. - Bal
# Check to see if we have keys that need to be made
- checkkeys
+ ${SSH_KEYGEN} -A
# Start SSHD
echo "starting $SSHD... \c" ; $SSHD
diff --git a/packet.c b/packet.c
index e7abb3416..990899418 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.291 2020/03/06 18:20:44 markus Exp $ */
+/* $OpenBSD: packet.c,v 1.301 2021/07/16 09:00:23 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -282,7 +282,8 @@ ssh_packet_set_input_hook(struct ssh *ssh, ssh_packet_hook_fn *hook, void *ctx)
int
ssh_packet_is_rekeying(struct ssh *ssh)
{
- return ssh->state->rekeying || ssh->kex->done == 0;
+ return ssh->state->rekeying ||
+ (ssh->kex != NULL && ssh->kex->done == 0);
}
/*
@@ -296,13 +297,13 @@ ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out)
int r;
if (none == NULL) {
- error("%s: cannot load cipher 'none'", __func__);
+ error_f("cannot load cipher 'none'");
return NULL;
}
if (ssh == NULL)
ssh = ssh_alloc_session_state();
if (ssh == NULL) {
- error("%s: could not allocate state", __func__);
+ error_f("could not allocate state");
return NULL;
}
state = ssh->state;
@@ -312,7 +313,7 @@ ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out)
(const u_char *)"", 0, NULL, 0, CIPHER_ENCRYPT)) != 0 ||
(r = cipher_init(&state->receive_context, none,
(const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0) {
- error("%s: cipher_init failed: %s", __func__, ssh_err(r));
+ error_fr(r, "cipher_init failed");
free(ssh); /* XXX need ssh_free_session_state? */
return NULL;
}
@@ -345,6 +346,8 @@ ssh_packet_set_mux(struct ssh *ssh)
{
ssh->state->mux = 1;
ssh->state->rekeying = 0;
+ kex_free(ssh->kex);
+ ssh->kex = NULL;
}
int
@@ -472,19 +475,7 @@ ssh_packet_get_bytes(struct ssh *ssh, u_int64_t *ibytes, u_int64_t *obytes)
int
ssh_packet_connection_af(struct ssh *ssh)
{
- struct sockaddr_storage to;
- socklen_t tolen = sizeof(to);
-
- memset(&to, 0, sizeof(to));
- if (getsockname(ssh->state->connection_out, (struct sockaddr *)&to,
- &tolen) == -1)
- return 0;
-#ifdef IPV4_IN_IPV6
- if (to.ss_family == AF_INET6 &&
- IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr))
- return AF_INET;
-#endif
- return to.ss_family;
+ return get_sock_af(ssh->state->connection_out);
}
/* Sets the connection into non-blocking mode. */
@@ -651,6 +642,8 @@ ssh_packet_close_internal(struct ssh *ssh, int do_close)
ssh->remote_ipaddr = NULL;
free(ssh->state);
ssh->state = NULL;
+ kex_free(ssh->kex);
+ ssh->kex = NULL;
}
}
@@ -691,7 +684,7 @@ static int
ssh_packet_init_compression(struct ssh *ssh)
{
if (!ssh->state->compression_buffer &&
- ((ssh->state->compression_buffer = sshbuf_new()) == NULL))
+ ((ssh->state->compression_buffer = sshbuf_new()) == NULL))
return SSH_ERR_ALLOC_FAIL;
return 0;
}
@@ -892,12 +885,12 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
max_blocks = &state->max_blocks_in;
}
if (state->newkeys[mode] != NULL) {
- debug("%s: rekeying %s, input %llu bytes %llu blocks, "
- "output %llu bytes %llu blocks", __func__, dir,
- (unsigned long long)state->p_read.bytes,
- (unsigned long long)state->p_read.blocks,
- (unsigned long long)state->p_send.bytes,
- (unsigned long long)state->p_send.blocks);
+ debug_f("rekeying %s, input %llu bytes %llu blocks, "
+ "output %llu bytes %llu blocks", dir,
+ (unsigned long long)state->p_read.bytes,
+ (unsigned long long)state->p_read.blocks,
+ (unsigned long long)state->p_send.bytes,
+ (unsigned long long)state->p_send.blocks);
kex_free_newkeys(state->newkeys[mode]);
state->newkeys[mode] = NULL;
}
@@ -915,7 +908,7 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
return r;
}
mac->enabled = 1;
- DBG(debug("%s: cipher_init_context: %s", __func__, dir));
+ DBG(debug_f("cipher_init_context: %s", dir));
cipher_free(*ccp);
*ccp = NULL;
if ((r = cipher_init(ccp, enc->cipher, enc->key, enc->key_len,
@@ -932,7 +925,7 @@ ssh_set_newkeys(struct ssh *ssh, int mode)
explicit_bzero(mac->key, mac->key_len); */
if ((comp->type == COMP_ZLIB ||
(comp->type == COMP_DELAYED &&
- state->after_authentication)) && comp->enabled == 0) {
+ state->after_authentication)) && comp->enabled == 0) {
if ((r = ssh_packet_init_compression(ssh)) < 0)
return r;
if (mode == MODE_OUT) {
@@ -1009,6 +1002,15 @@ ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len)
(state->p_read.blocks > state->max_blocks_in));
}
+int
+ssh_packet_check_rekey(struct ssh *ssh)
+{
+ if (!ssh_packet_need_rekeying(ssh, 0))
+ return 0;
+ debug3_f("rekex triggered");
+ return kex_start_rekex(ssh);
+}
+
/*
* Delayed compression for SSH2 is enabled after authentication:
* This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent,
@@ -1138,8 +1140,8 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
if (tmp > state->extra_pad)
return SSH_ERR_INVALID_ARGUMENT;
pad = state->extra_pad - tmp;
- DBG(debug3("%s: adding %d (len %d padlen %d extra_pad %d)",
- __func__, pad, len, padlen, state->extra_pad));
+ DBG(debug3_f("adding %d (len %d padlen %d extra_pad %d)",
+ pad, len, padlen, state->extra_pad));
tmp = padlen;
padlen += pad;
/* Check whether padlen calculation overflowed */
@@ -1254,7 +1256,7 @@ ssh_packet_send2(struct ssh *ssh)
*/
if ((need_rekey || state->rekeying) && !ssh_packet_type_is_kex(type)) {
if (need_rekey)
- debug3("%s: rekex triggered", __func__);
+ debug3_f("rekex triggered");
debug("enqueue packet: %u", type);
p = calloc(1, sizeof(*p));
if (p == NULL)
@@ -1296,8 +1298,7 @@ ssh_packet_send2(struct ssh *ssh)
*/
if (ssh_packet_need_rekeying(ssh,
sshbuf_len(p->payload))) {
- debug3("%s: queued packet triggered rekex",
- __func__);
+ debug3_f("queued packet triggered rekex");
return kex_start_rekex(ssh);
}
debug("dequeue packet: %u", type);
@@ -1416,7 +1417,7 @@ ssh_packet_read(struct ssh *ssh)
int r;
if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "read");
return type;
}
@@ -1474,7 +1475,7 @@ ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
(r = sshbuf_get_u8(state->incoming_packet, typep)) != 0)
return r;
if (ssh_packet_log_type(*typep))
- debug3("%s: type %u", __func__, *typep);
+ debug3_f("type %u", *typep);
/* sshbuf_dump(state->incoming_packet, stderr); */
/* reset for next packet */
state->packlen = 0;
@@ -1703,12 +1704,8 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
/* reset for next packet */
state->packlen = 0;
- /* do we need to rekey? */
- if (ssh_packet_need_rekeying(ssh, 0)) {
- debug3("%s: rekex triggered", __func__);
- if ((r = kex_start_rekex(ssh)) != 0)
- return r;
- }
+ if ((r = ssh_packet_check_rekey(ssh)) != 0)
+ return r;
out:
return r;
}
@@ -1831,7 +1828,7 @@ ssh_packet_send_debug(struct ssh *ssh, const char *fmt,...)
(r = sshpkt_put_cstring(ssh, "")) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send DEBUG");
}
void
@@ -1887,15 +1884,13 @@ sshpkt_vfatal(struct ssh *ssh, int r, const char *fmt, va_list ap)
default:
if (vasprintf(&tag, fmt, ap) == -1) {
ssh_packet_clear_keys(ssh);
- logdie("%s: could not allocate failure message",
- __func__);
+ logdie_f("could not allocate failure message");
}
ssh_packet_clear_keys(ssh);
errno = oerrno;
- logdie("%s%sConnection %s %s: %s",
+ logdie_r(r, "%s%sConnection %s %s",
tag != NULL ? tag : "", tag != NULL ? ": " : "",
- ssh->state->server_side ? "from" : "to",
- remote_id, ssh_err(r));
+ ssh->state->server_side ? "from" : "to", remote_id);
}
}
@@ -1908,7 +1903,7 @@ sshpkt_fatal(struct ssh *ssh, int r, const char *fmt, ...)
sshpkt_vfatal(ssh, r, fmt, ap);
/* NOTREACHED */
va_end(ap);
- logdie("%s: should have exited", __func__);
+ logdie_f("should have exited");
}
/*
@@ -2067,30 +2062,9 @@ ssh_packet_not_very_much_data_to_write(struct ssh *ssh)
void
ssh_packet_set_tos(struct ssh *ssh, int tos)
{
-#ifndef IP_TOS_IS_BROKEN
if (!ssh_packet_connection_is_on_socket(ssh) || tos == INT_MAX)
return;
- switch (ssh_packet_connection_af(ssh)) {
-# ifdef IP_TOS
- case AF_INET:
- debug3("%s: set IP_TOS 0x%02x", __func__, tos);
- if (setsockopt(ssh->state->connection_in,
- IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == -1)
- error("setsockopt IP_TOS %d: %.100s:",
- tos, strerror(errno));
- break;
-# endif /* IP_TOS */
-# ifdef IPV6_TCLASS
- case AF_INET6:
- debug3("%s: set IPV6_TCLASS 0x%02x", __func__, tos);
- if (setsockopt(ssh->state->connection_in,
- IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos)) == -1)
- error("setsockopt IPV6_TCLASS %d: %.100s:",
- tos, strerror(errno));
- break;
-# endif /* IPV6_TCLASS */
- }
-#endif /* IP_TOS_IS_BROKEN */
+ set_sock_tos(ssh->state->connection_in, tos);
}
/* Informs that the current session is interactive. Sets IP flags for that. */
@@ -2111,8 +2085,7 @@ ssh_packet_set_interactive(struct ssh *ssh, int interactive, int qos_interactive
if (!ssh_packet_connection_is_on_socket(ssh))
return;
set_nodelay(state->connection_in);
- ssh_packet_set_tos(ssh, interactive ? qos_interactive :
- qos_bulk);
+ ssh_packet_set_tos(ssh, interactive ? qos_interactive : qos_bulk);
}
/* Returns true if the current connection is interactive. */
@@ -2211,7 +2184,7 @@ ssh_packet_set_postauth(struct ssh *ssh)
{
int r;
- debug("%s: called", __func__);
+ debug_f("called");
/* This was set in net child, but is not visible in user child */
ssh->state->after_authentication = 1;
ssh->state->rekeying = 0;
@@ -2228,9 +2201,7 @@ kex_to_blob(struct sshbuf *m, struct kex *kex)
{
int r;
- if ((r = sshbuf_put_string(m, kex->session_id,
- kex->session_id_len)) != 0 ||
- (r = sshbuf_put_u32(m, kex->we_need)) != 0 ||
+ if ((r = sshbuf_put_u32(m, kex->we_need)) != 0 ||
(r = sshbuf_put_cstring(m, kex->hostkey_alg)) != 0 ||
(r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 ||
(r = sshbuf_put_u32(m, kex->hostkey_nid)) != 0 ||
@@ -2239,6 +2210,7 @@ kex_to_blob(struct sshbuf *m, struct kex *kex)
(r = sshbuf_put_stringb(m, kex->peer)) != 0 ||
(r = sshbuf_put_stringb(m, kex->client_version)) != 0 ||
(r = sshbuf_put_stringb(m, kex->server_version)) != 0 ||
+ (r = sshbuf_put_stringb(m, kex->session_id)) != 0 ||
(r = sshbuf_put_u32(m, kex->flags)) != 0)
return r;
return 0;
@@ -2391,8 +2363,7 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp)
if ((kex = kex_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
- if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 ||
- (r = sshbuf_get_u32(m, &kex->we_need)) != 0 ||
+ if ((r = sshbuf_get_u32(m, &kex->we_need)) != 0 ||
(r = sshbuf_get_cstring(m, &kex->hostkey_alg, NULL)) != 0 ||
(r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 ||
(r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_nid)) != 0 ||
@@ -2401,6 +2372,7 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp)
(r = sshbuf_get_stringb(m, kex->peer)) != 0 ||
(r = sshbuf_get_stringb(m, kex->client_version)) != 0 ||
(r = sshbuf_get_stringb(m, kex->server_version)) != 0 ||
+ (r = sshbuf_get_stringb(m, kex->session_id)) != 0 ||
(r = sshbuf_get_u32(m, &kex->flags)) != 0)
goto out;
kex->server = 1;
@@ -2445,7 +2417,7 @@ ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m)
(r = sshbuf_get_u64(m, &state->p_read.bytes)) != 0)
return r;
/*
- * We set the time here so that in post-auth privsep slave we
+ * We set the time here so that in post-auth privsep child we
* count from the completion of the authentication.
*/
state->rekey_time = monotime();
@@ -2467,7 +2439,7 @@ ssh_packet_set_state(struct ssh *ssh, struct sshbuf *m)
if (sshbuf_len(m))
return SSH_ERR_INVALID_FORMAT;
- debug3("%s: done", __func__);
+ debug3_f("done");
return 0;
}
@@ -2658,7 +2630,7 @@ ssh_packet_send_mux(struct ssh *ssh)
cp = sshbuf_mutable_ptr(state->outgoing_packet);
type = cp[5];
if (ssh_packet_log_type(type))
- debug3("%s: type %u", __func__, type);
+ debug3_f("type %u", type);
/* drop everything, but the connection protocol */
if (type >= SSH2_MSG_CONNECTION_MIN &&
type <= SSH2_MSG_CONNECTION_MAX) {
diff --git a/packet.h b/packet.h
index c2544bd96..2ad0e70cf 100644
--- a/packet.h
+++ b/packet.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.h,v 1.92 2020/03/06 18:11:10 markus Exp $ */
+/* $OpenBSD: packet.h,v 1.93 2021/07/16 09:00:23 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -105,6 +105,7 @@ void ssh_packet_clear_keys(struct ssh *);
void ssh_clear_newkeys(struct ssh *, int);
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);
diff --git a/platform-tracing.c b/platform-tracing.c
index 4c80a282c..0daf2a86f 100644
--- a/platform-tracing.c
+++ b/platform-tracing.c
@@ -17,6 +17,9 @@
#include "includes.h"
#include <sys/types.h>
+#ifdef HAVE_SYS_PROCCTL_H
+#include <sys/procctl.h>
+#endif
#if defined(HAVE_SYS_PRCTL_H)
#include <sys/prctl.h> /* For prctl() and PR_SET_DUMPABLE */
#endif
@@ -33,6 +36,13 @@
void
platform_disable_tracing(int strict)
{
+#if defined(HAVE_PROCCTL) && defined(PROC_TRACE_CTL)
+ /* On FreeBSD, we should make this process untraceable */
+ int disable_trace = PROC_TRACE_CTL_DISABLE;
+
+ if (procctl(P_PID, 0, PROC_TRACE_CTL, &disable_trace) && strict)
+ fatal("unable to make the process untraceable");
+#endif
#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
/* Disable ptrace on Linux without sgid bit */
if (prctl(PR_SET_DUMPABLE, 0) != 0 && strict)
diff --git a/readconf.c b/readconf.c
index 2afcbaeca..bcca6ed47 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.329 2020/04/24 03:33:21 dtucker Exp $ */
+/* $OpenBSD: readconf.c,v 1.363 2021/09/16 05:36:03 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -145,14 +145,15 @@ typedef enum {
oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
oGatewayPorts, oExitOnForwardFailure,
oPasswordAuthentication,
- oChallengeResponseAuthentication, oXAuthLocation,
+ oXAuthLocation,
oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward,
+ oPermitRemoteOpen,
oCertificateFile, oAddKeysToAgent, oIdentityAgent,
oUser, oEscapeChar, oProxyCommand,
oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
oTCPKeepAlive, oNumberOfPasswordPrompts,
- oLogFacility, oLogLevel, oCiphers, oMacs,
+ oLogFacility, oLogLevel, oLogVerbose, oCiphers, oMacs,
oPubkeyAuthentication,
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
@@ -166,13 +167,14 @@ typedef enum {
oTunnel, oTunnelDevice,
oLocalCommand, oPermitLocalCommand, oRemoteCommand,
oVisualHostKey,
- oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
+ oKexAlgorithms, oIPQoS, oRequestTTY, oSessionType, oStdinNull,
+ oForkAfterAuthentication, oIgnoreUnknown, oProxyUseFdpass,
oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
- oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes,
- oPubkeyAcceptedKeyTypes, oCASignatureAlgorithms, oProxyJump,
- oSecurityKeyProvider,
+ oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
+ oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
+ oSecurityKeyProvider, oKnownHostsCommand,
oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
} OpCodes;
@@ -227,12 +229,12 @@ static struct {
{ "passwordauthentication", oPasswordAuthentication },
{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
{ "kbdinteractivedevices", oKbdInteractiveDevices },
+ { "challengeresponseauthentication", oKbdInteractiveAuthentication }, /* alias */
+ { "skeyauthentication", oKbdInteractiveAuthentication }, /* alias */
+ { "tisauthentication", oKbdInteractiveAuthentication }, /* alias */
{ "pubkeyauthentication", oPubkeyAuthentication },
{ "dsaauthentication", oPubkeyAuthentication }, /* alias */
{ "hostbasedauthentication", oHostbasedAuthentication },
- { "challengeresponseauthentication", oChallengeResponseAuthentication },
- { "skeyauthentication", oUnsupported },
- { "tisauthentication", oChallengeResponseAuthentication }, /* alias */
{ "identityfile", oIdentityFile },
{ "identityfile2", oIdentityFile }, /* obsolete */
{ "identitiesonly", oIdentitiesOnly },
@@ -247,6 +249,7 @@ static struct {
{ "macs", oMacs },
{ "remoteforward", oRemoteForward },
{ "localforward", oLocalForward },
+ { "permitremoteopen", oPermitRemoteOpen },
{ "user", oUser },
{ "host", oHost },
{ "match", oMatch },
@@ -263,6 +266,7 @@ static struct {
{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
{ "syslogfacility", oLogFacility },
{ "loglevel", oLogLevel },
+ { "logverbose", oLogVerbose },
{ "dynamicforward", oDynamicForward },
{ "preferredauthentications", oPreferredAuthentications },
{ "hostkeyalgorithms", oHostKeyAlgorithms },
@@ -294,6 +298,9 @@ static struct {
{ "kexalgorithms", oKexAlgorithms },
{ "ipqos", oIPQoS },
{ "requesttty", oRequestTTY },
+ { "sessiontype", oSessionType },
+ { "stdinnull", oStdinNull },
+ { "forkafterauthentication", oForkAfterAuthentication },
{ "proxyusefdpass", oProxyUseFdpass },
{ "canonicaldomains", oCanonicalDomains },
{ "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
@@ -305,23 +312,33 @@ static struct {
{ "revokedhostkeys", oRevokedHostKeys },
{ "fingerprinthash", oFingerprintHash },
{ "updatehostkeys", oUpdateHostkeys },
- { "hostbasedkeytypes", oHostbasedKeyTypes },
- { "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes },
+ { "hostbasedacceptedalgorithms", oHostbasedAcceptedAlgorithms },
+ { "hostbasedkeytypes", oHostbasedAcceptedAlgorithms }, /* obsolete */
+ { "pubkeyacceptedalgorithms", oPubkeyAcceptedAlgorithms },
+ { "pubkeyacceptedkeytypes", oPubkeyAcceptedAlgorithms }, /* obsolete */
{ "ignoreunknown", oIgnoreUnknown },
{ "proxyjump", oProxyJump },
{ "securitykeyprovider", oSecurityKeyProvider },
+ { "knownhostscommand", oKnownHostsCommand },
{ NULL, oBadOption }
};
-static char *kex_default_pk_alg_filtered;
+static const char *lookup_opcode_name(OpCodes code);
const char *
kex_default_pk_alg(void)
{
- if (kex_default_pk_alg_filtered == NULL)
- fatal("kex_default_pk_alg not initialized.");
- return kex_default_pk_alg_filtered;
+ static char *pkalgs;
+
+ if (pkalgs == NULL) {
+ char *all_key;
+
+ all_key = sshkey_alg_list(0, 0, 1, ',');
+ pkalgs = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
+ free(all_key);
+ }
+ return pkalgs;
}
char *
@@ -337,7 +354,7 @@ ssh_connection_hash(const char *thishost, const char *host, const char *portstr,
ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
ssh_digest_update(md, user, strlen(user)) < 0 ||
ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
- fatal("%s: mux digest failed", __func__);
+ fatal_f("mux digest failed");
ssh_digest_free(md);
return tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
}
@@ -445,7 +462,7 @@ add_certificate_file(Options *options, const char *path, int userprovided)
for (i = 0; i < options->num_certificate_files; i++) {
if (options->certificate_file_userprovided[i] == userprovided &&
strcmp(options->certificate_files[i], path) == 0) {
- debug2("%s: ignoring duplicate key %s", __func__, path);
+ debug2_f("ignoring duplicate key %s", path);
return;
}
}
@@ -476,7 +493,7 @@ add_identity_file(Options *options, const char *dir, const char *filename,
for (i = 0; i < options->num_identity_files; i++) {
if (options->identity_file_userprovided[i] == userprovided &&
strcmp(options->identity_files[i], path) == 0) {
- debug2("%s: ignoring duplicate key %s", __func__, path);
+ debug2_f("ignoring duplicate key %s", path);
free(path);
return;
}
@@ -509,7 +526,7 @@ execute_in_shell(const char *cmd)
{
char *shell;
pid_t pid;
- int devnull, status;
+ int status;
if ((shell = getenv("SHELL")) == NULL)
shell = _PATH_BSHELL;
@@ -519,23 +536,14 @@ execute_in_shell(const char *cmd)
shell, strerror(errno));
}
- /* Need this to redirect subprocess stdin/out */
- if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1)
- fatal("open(/dev/null): %s", strerror(errno));
-
debug("Executing command: '%.500s'", cmd);
/* Fork and execute the command. */
if ((pid = fork()) == 0) {
char *argv[4];
- /* Redirect child stdin and stdout. Leave stderr */
- if (dup2(devnull, STDIN_FILENO) == -1)
- fatal("dup2: %s", strerror(errno));
- if (dup2(devnull, STDOUT_FILENO) == -1)
- fatal("dup2: %s", strerror(errno));
- if (devnull > STDERR_FILENO)
- close(devnull);
+ if (stdfd_devnull(1, 1, 0) == -1)
+ fatal_f("stdfd_devnull failed");
closefrom(STDERR_FILENO + 1);
argv[0] = shell;
@@ -552,13 +560,11 @@ execute_in_shell(const char *cmd)
}
/* Parent. */
if (pid == -1)
- fatal("%s: fork: %.100s", __func__, strerror(errno));
-
- close(devnull);
+ fatal_f("fork: %.100s", strerror(errno));
while (waitpid(pid, &status, 0) == -1) {
if (errno != EINTR && errno != EAGAIN)
- fatal("%s: waitpid: %s", __func__, strerror(errno));
+ fatal_f("waitpid: %s", strerror(errno));
}
if (!WIFEXITED(status)) {
error("command '%.100s' exited abnormally", cmd);
@@ -601,25 +607,33 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,
debug2("checking match for '%s' host %s originally %s",
cp, host, original_host);
while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') {
- criteria = NULL;
+ /* Terminate on comment */
+ if (*attrib == '#') {
+ cp = NULL; /* mark all arguments consumed */
+ break;
+ }
+ arg = criteria = NULL;
this_result = 1;
if ((negate = attrib[0] == '!'))
attrib++;
- /* criteria "all" and "canonical" have no argument */
+ /* Criterion "all" has no argument and must appear alone */
if (strcasecmp(attrib, "all") == 0) {
- if (attributes > 1 ||
- ((arg = strdelim(&cp)) != NULL && *arg != '\0')) {
+ if (attributes > 1 || ((arg = strdelim(&cp)) != NULL &&
+ *arg != '\0' && *arg != '#')) {
error("%.200s line %d: '%s' cannot be combined "
"with other Match attributes",
filename, linenum, oattrib);
result = -1;
goto out;
}
+ if (arg != NULL && *arg == '#')
+ cp = NULL; /* mark all arguments consumed */
if (result)
result = negate ? 0 : 1;
goto out;
}
attributes++;
+ /* criteria "final" and "canonical" have no argument */
if (strcasecmp(attrib, "canonical") == 0 ||
strcasecmp(attrib, "final") == 0) {
/*
@@ -638,7 +652,8 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,
continue;
}
/* All other criteria require an argument */
- if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
+ if ((arg = strdelim(&cp)) == NULL ||
+ *arg == '\0' || *arg == '#') {
error("Missing Match criteria for %s", attrib);
result = -1;
goto out;
@@ -664,7 +679,7 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,
if (r == (negate ? 1 : 0))
this_result = result = 0;
} else if (strcasecmp(attrib, "exec") == 0) {
- char *conn_hash_hex;
+ char *conn_hash_hex, *keyalias;
if (gethostname(thishost, sizeof(thishost)) == -1)
fatal("gethostname: %s", strerror(errno));
@@ -674,13 +689,16 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,
snprintf(uidstr, sizeof(uidstr), "%llu",
(unsigned long long)pw->pw_uid);
conn_hash_hex = ssh_connection_hash(thishost, host,
- portstr, ruser);
+ portstr, ruser);
+ keyalias = options->host_key_alias ?
+ options->host_key_alias : host;
cmd = percent_expand(arg,
"C", conn_hash_hex,
"L", shorthost,
"d", pw->pw_dir,
"h", host,
+ "k", keyalias,
"l", thishost,
"n", original_host,
"p", portstr,
@@ -735,7 +753,7 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,
static void
rm_env(Options *options, const char *arg, const char *filename, int linenum)
{
- int i, j;
+ int i, j, onum_send_env = options->num_send_env;
char *cp;
/* Remove an environment variable */
@@ -758,6 +776,11 @@ rm_env(Options *options, const char *arg, const char *filename, int linenum)
options->num_send_env--;
/* NB. don't increment i */
}
+ if (onum_send_env != options->num_send_env) {
+ options->send_env = xrecallocarray(options->send_env,
+ onum_send_env, options->num_send_env,
+ sizeof(*options->send_env));
+ }
}
/*
@@ -853,6 +876,12 @@ static const struct multistate multistate_requesttty[] = {
{ "auto", REQUEST_TTY_AUTO },
{ NULL, -1 }
};
+static const struct multistate multistate_sessiontype[] = {
+ { "none", SESSION_TYPE_NONE },
+ { "subsystem", SESSION_TYPE_SUBSYSTEM },
+ { "default", SESSION_TYPE_DEFAULT },
+ { NULL, -1 }
+};
static const struct multistate multistate_canonicalizehostname[] = {
{ "true", SSH_CANONICALISE_YES },
{ "false", SSH_CANONICALISE_NO },
@@ -869,6 +898,23 @@ static const struct multistate multistate_compression[] = {
{ NULL, -1 }
};
+static int
+parse_multistate_value(const char *arg, const char *filename, int linenum,
+ const struct multistate *multistate_ptr)
+{
+ int i;
+
+ if (!arg || *arg == '\0') {
+ error("%s line %d: missing argument.", filename, linenum);
+ return -1;
+ }
+ for (i = 0; multistate_ptr[i].key != NULL; i++) {
+ if (strcasecmp(arg, multistate_ptr[i].key) == 0)
+ return multistate_ptr[i].value;
+ }
+ return -1;
+}
+
/*
* Processes a single option line as used in the configuration files. This
* only sets those values that have not already been set.
@@ -888,9 +934,9 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host,
const char *original_host, char *line, const char *filename,
int linenum, int *activep, int flags, int *want_final_pass, int depth)
{
- char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
- char **cpptr, fwdarg[256];
- u_int i, *uintptr, max_entries = 0;
+ char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p, ch;
+ char **cpptr, ***cppptr, fwdarg[256];
+ u_int i, *uintptr, uvalue, max_entries = 0;
int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
int remotefwd, dynamicfwd;
LogLevel *log_level_ptr;
@@ -902,6 +948,9 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host,
struct allowed_cname *cname;
glob_t gl;
const char *errstr;
+ char **oav = NULL, **av;
+ int oac = 0, ac;
+ int ret = -1;
if (activep == NULL) { /* We are processing a command line directive */
cmdline = 1;
@@ -917,43 +966,63 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host,
line[len] = '\0';
}
- s = line;
+ str = line;
/* Get the keyword. (Each line is supposed to begin with a keyword). */
- if ((keyword = strdelim(&s)) == NULL)
+ if ((keyword = strdelim(&str)) == NULL)
return 0;
/* Ignore leading whitespace. */
if (*keyword == '\0')
- keyword = strdelim(&s);
+ keyword = strdelim(&str);
if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
return 0;
/* Match lowercase keyword */
lowercase(keyword);
+ /* Prepare to parse remainder of line */
+ if (str != NULL)
+ str += strspn(str, WHITESPACE);
+ if (str == NULL || *str == '\0') {
+ error("%s line %d: no argument after keyword \"%s\"",
+ filename, linenum, keyword);
+ return -1;
+ }
opcode = parse_token(keyword, filename, linenum,
options->ignored_unknown);
+ if (argv_split(str, &oac, &oav, 1) != 0) {
+ error("%s line %d: invalid quotes", filename, linenum);
+ return -1;
+ }
+ ac = oac;
+ av = oav;
switch (opcode) {
case oBadOption:
/* don't panic, but count bad options */
- return -1;
+ goto out;
case oIgnore:
- return 0;
+ argv_consume(&ac);
+ break;
case oIgnoredUnknownOption:
debug("%s line %d: Ignored unknown option \"%s\"",
filename, linenum, keyword);
- return 0;
+ argv_consume(&ac);
+ break;
case oConnectTimeout:
intptr = &options->connection_timeout;
parse_time:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%s line %d: missing time value.",
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ error("%s line %d: missing time value.",
filename, linenum);
+ goto out;
+ }
if (strcmp(arg, "none") == 0)
value = -1;
- else if ((value = convtime(arg)) == -1)
- fatal("%s line %d: invalid time value.",
+ else if ((value = convtime(arg)) == -1) {
+ error("%s line %d: invalid time value.",
filename, linenum);
+ goto out;
+ }
if (*activep && *intptr == -1)
*intptr = value;
break;
@@ -961,10 +1030,12 @@ parse_time:
case oForwardAgent:
intptr = &options->forward_agent;
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%s line %d: missing argument.",
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ error("%s line %d: missing argument.",
filename, linenum);
+ goto out;
+ }
value = -1;
multistate_ptr = multistate_flag;
@@ -991,20 +1062,13 @@ parse_time:
parse_flag:
multistate_ptr = multistate_flag;
parse_multistate:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%s line %d: missing argument.",
- filename, linenum);
- value = -1;
- for (i = 0; multistate_ptr[i].key != NULL; i++) {
- if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
- value = multistate_ptr[i].value;
- break;
- }
- }
- if (value == -1)
- fatal("%s line %d: unsupported option \"%s\".",
+ arg = argv_next(&ac, &av);
+ if ((value = parse_multistate_value(arg, filename, linenum,
+ multistate_ptr)) == -1) {
+ error("%s line %d: unsupported option \"%s\".",
filename, linenum, arg);
+ goto out;
+ }
if (*activep && *intptr == -1)
*intptr = value;
break;
@@ -1045,10 +1109,6 @@ parse_time:
intptr = &options->hostbased_authentication;
goto parse_flag;
- case oChallengeResponseAuthentication:
- intptr = &options->challenge_response_authentication;
- goto parse_flag;
-
case oGssAuthentication:
intptr = &options->gss_authentication;
goto parse_flag;
@@ -1093,25 +1153,31 @@ parse_time:
goto parse_int;
case oRekeyLimit:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename,
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ error("%.200s line %d: Missing argument.", filename,
linenum);
+ goto out;
+ }
if (strcmp(arg, "default") == 0) {
val64 = 0;
} else {
- if (scan_scaled(arg, &val64) == -1)
- fatal("%.200s line %d: Bad number '%s': %s",
+ if (scan_scaled(arg, &val64) == -1) {
+ error("%.200s line %d: Bad number '%s': %s",
filename, linenum, arg, strerror(errno));
- if (val64 != 0 && val64 < 16)
- fatal("%.200s line %d: RekeyLimit too small",
+ goto out;
+ }
+ if (val64 != 0 && val64 < 16) {
+ error("%.200s line %d: RekeyLimit too small",
filename, linenum);
+ goto out;
+ }
}
if (*activep && options->rekey_limit == -1)
options->rekey_limit = val64;
- if (s != NULL) { /* optional rekey interval present */
- if (strcmp(s, "none") == 0) {
- (void)strdelim(&s); /* discard */
+ if (ac != 0) { /* optional rekey interval present */
+ if (strcmp(av[0], "none") == 0) {
+ (void)argv_next(&ac, &av); /* discard */
break;
}
intptr = &options->rekey_interval;
@@ -1120,31 +1186,40 @@ parse_time:
break;
case oIdentityFile:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ error("%.200s line %d: Missing argument.",
+ filename, linenum);
+ goto out;
+ }
if (*activep) {
intptr = &options->num_identity_files;
- if (*intptr >= SSH_MAX_IDENTITY_FILES)
- fatal("%.200s line %d: Too many identity files specified (max %d).",
- filename, linenum, SSH_MAX_IDENTITY_FILES);
+ if (*intptr >= SSH_MAX_IDENTITY_FILES) {
+ error("%.200s line %d: Too many identity files "
+ "specified (max %d).", filename, linenum,
+ SSH_MAX_IDENTITY_FILES);
+ goto out;
+ }
add_identity_file(options, NULL,
arg, flags & SSHCONF_USERCONF);
}
break;
case oCertificateFile:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.",
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ error("%.200s line %d: Missing argument.",
filename, linenum);
+ goto out;
+ }
if (*activep) {
intptr = &options->num_certificate_files;
if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
- fatal("%.200s line %d: Too many certificate "
+ error("%.200s line %d: Too many certificate "
"files specified (max %d).",
filename, linenum,
SSH_MAX_CERTIFICATE_FILES);
+ goto out;
}
add_certificate_file(options, arg,
flags & SSHCONF_USERCONF);
@@ -1158,10 +1233,12 @@ parse_time:
case oUser:
charptr = &options->user;
parse_string:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.",
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ error("%.200s line %d: Missing argument.",
filename, linenum);
+ goto out;
+ }
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
@@ -1171,16 +1248,35 @@ parse_string:
uintptr = &options->num_system_hostfiles;
max_entries = SSH_MAX_HOSTS_FILES;
parse_char_array:
- if (*activep && *uintptr == 0) {
- while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
- if ((*uintptr) >= max_entries)
- fatal("%s line %d: "
- "too many known hosts files.",
- filename, linenum);
+ i = 0;
+ value = *uintptr == 0; /* was array empty when we started? */
+ while ((arg = argv_next(&ac, &av)) != NULL) {
+ if (*arg == '\0') {
+ error("%s line %d: keyword %s empty argument",
+ filename, linenum, keyword);
+ goto out;
+ }
+ /* Allow "none" only in first position */
+ if (strcasecmp(arg, "none") == 0) {
+ if (i > 0 || ac > 0) {
+ error("%s line %d: keyword %s \"none\" "
+ "argument must appear alone.",
+ filename, linenum, keyword);
+ goto out;
+ }
+ }
+ i++;
+ if (*activep && value) {
+ if ((*uintptr) >= max_entries) {
+ error("%s line %d: too many %s "
+ "entries.", filename, linenum,
+ keyword);
+ goto out;
+ }
cpptr[(*uintptr)++] = xstrdup(arg);
}
}
- return 0;
+ break;
case oUserKnownHostsFile:
cpptr = (char **)&options->user_hostfiles;
@@ -1216,40 +1312,56 @@ parse_char_array:
charptr = &options->sk_provider;
goto parse_string;
+ case oKnownHostsCommand:
+ charptr = &options->known_hosts_command;
+ goto parse_command;
+
case oProxyCommand:
charptr = &options->proxy_command;
/* Ignore ProxyCommand if ProxyJump already specified */
if (options->jump_host != NULL)
charptr = &options->jump_host; /* Skip below */
parse_command:
- if (s == NULL)
- fatal("%.200s line %d: Missing argument.", filename, linenum);
- len = strspn(s, WHITESPACE "=");
+ if (str == NULL) {
+ error("%.200s line %d: Missing argument.",
+ filename, linenum);
+ goto out;
+ }
+ len = strspn(str, WHITESPACE "=");
if (*activep && *charptr == NULL)
- *charptr = xstrdup(s + len);
- return 0;
+ *charptr = xstrdup(str + len);
+ argv_consume(&ac);
+ break;
case oProxyJump:
- if (s == NULL) {
- fatal("%.200s line %d: Missing argument.",
+ if (str == NULL) {
+ error("%.200s line %d: Missing argument.",
filename, linenum);
+ goto out;
}
- len = strspn(s, WHITESPACE "=");
- if (parse_jump(s + len, options, *activep) == -1) {
- fatal("%.200s line %d: Invalid ProxyJump \"%s\"",
- filename, linenum, s + len);
+ len = strspn(str, WHITESPACE "=");
+ /* XXX use argv? */
+ if (parse_jump(str + len, options, *activep) == -1) {
+ error("%.200s line %d: Invalid ProxyJump \"%s\"",
+ filename, linenum, str + len);
+ goto out;
}
- return 0;
+ argv_consume(&ac);
+ break;
case oPort:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.",
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ error("%.200s line %d: Missing argument.",
filename, linenum);
+ goto out;
+ }
value = a2port(arg);
- if (value <= 0)
- fatal("%.200s line %d: Bad port '%s'.",
+ if (value <= 0) {
+ error("%.200s line %d: Bad port '%s'.",
filename, linenum, arg);
+ goto out;
+ }
if (*activep && options->port == -1)
options->port = value;
break;
@@ -1257,113 +1369,169 @@ parse_command:
case oConnectionAttempts:
intptr = &options->connection_attempts;
parse_int:
- arg = strdelim(&s);
- if ((errstr = atoi_err(arg, &value)) != NULL)
- fatal("%s line %d: integer value %s.",
+ arg = argv_next(&ac, &av);
+ if ((errstr = atoi_err(arg, &value)) != NULL) {
+ error("%s line %d: integer value %s.",
filename, linenum, errstr);
+ goto out;
+ }
if (*activep && *intptr == -1)
*intptr = value;
break;
case oCiphers:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ error("%.200s line %d: Missing argument.",
+ filename, linenum);
+ goto out;
+ }
if (*arg != '-' &&
- !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg))
- fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
+ !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){
+ error("%.200s line %d: Bad SSH2 cipher spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
+ goto out;
+ }
if (*activep && options->ciphers == NULL)
options->ciphers = xstrdup(arg);
break;
case oMacs:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ error("%.200s line %d: Missing argument.",
+ filename, linenum);
+ goto out;
+ }
if (*arg != '-' &&
- !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg))
- fatal("%.200s line %d: Bad SSH2 MAC spec '%s'.",
+ !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) {
+ error("%.200s line %d: Bad SSH2 MAC spec '%s'.",
filename, linenum, arg ? arg : "<NONE>");
+ goto out;
+ }
if (*activep && options->macs == NULL)
options->macs = xstrdup(arg);
break;
case oKexAlgorithms:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.",
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ error("%.200s line %d: Missing argument.",
filename, linenum);
+ goto out;
+ }
if (*arg != '-' &&
!kex_names_valid(*arg == '+' || *arg == '^' ?
- arg + 1 : arg))
- fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
+ arg + 1 : arg)) {
+ error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
filename, linenum, arg ? arg : "<NONE>");
+ goto out;
+ }
if (*activep && options->kex_algorithms == NULL)
options->kex_algorithms = xstrdup(arg);
break;
case oHostKeyAlgorithms:
charptr = &options->hostkeyalgorithms;
-parse_keytypes:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.",
+parse_pubkey_algos:
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ error("%.200s line %d: Missing argument.",
filename, linenum);
+ goto out;
+ }
if (*arg != '-' &&
!sshkey_names_valid2(*arg == '+' || *arg == '^' ?
- arg + 1 : arg, 1))
- fatal("%s line %d: Bad key types '%s'.",
- filename, linenum, arg ? arg : "<NONE>");
+ arg + 1 : arg, 1)) {
+ error("%s line %d: Bad key types '%s'.",
+ filename, linenum, arg ? arg : "<NONE>");
+ goto out;
+ }
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
case oCASignatureAlgorithms:
charptr = &options->ca_sign_algorithms;
- goto parse_keytypes;
+ goto parse_pubkey_algos;
case oLogLevel:
log_level_ptr = &options->log_level;
- arg = strdelim(&s);
+ arg = argv_next(&ac, &av);
value = log_level_number(arg);
- if (value == SYSLOG_LEVEL_NOT_SET)
- fatal("%.200s line %d: unsupported log level '%s'",
+ if (value == SYSLOG_LEVEL_NOT_SET) {
+ error("%.200s line %d: unsupported log level '%s'",
filename, linenum, arg ? arg : "<NONE>");
+ goto out;
+ }
if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
*log_level_ptr = (LogLevel) value;
break;
case oLogFacility:
log_facility_ptr = &options->log_facility;
- arg = strdelim(&s);
+ arg = argv_next(&ac, &av);
value = log_facility_number(arg);
- if (value == SYSLOG_FACILITY_NOT_SET)
- fatal("%.200s line %d: unsupported log facility '%s'",
+ if (value == SYSLOG_FACILITY_NOT_SET) {
+ error("%.200s line %d: unsupported log facility '%s'",
filename, linenum, arg ? arg : "<NONE>");
+ goto out;
+ }
if (*log_facility_ptr == -1)
*log_facility_ptr = (SyslogFacility) value;
break;
+ case oLogVerbose:
+ cppptr = &options->log_verbose;
+ uintptr = &options->num_log_verbose;
+ i = 0;
+ while ((arg = argv_next(&ac, &av)) != NULL) {
+ if (*arg == '\0') {
+ error("%s line %d: keyword %s empty argument",
+ filename, linenum, keyword);
+ goto out;
+ }
+ /* Allow "none" only in first position */
+ if (strcasecmp(arg, "none") == 0) {
+ if (i > 0 || ac > 0) {
+ error("%s line %d: keyword %s \"none\" "
+ "argument must appear alone.",
+ filename, linenum, keyword);
+ goto out;
+ }
+ }
+ i++;
+ if (*activep && *uintptr == 0) {
+ *cppptr = xrecallocarray(*cppptr, *uintptr,
+ *uintptr + 1, sizeof(**cppptr));
+ (*cppptr)[(*uintptr)++] = xstrdup(arg);
+ }
+ }
+ break;
+
case oLocalForward:
case oRemoteForward:
case oDynamicForward:
- arg = strdelim(&s);
- if (arg == NULL || *arg == '\0')
- fatal("%.200s line %d: Missing port argument.",
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ error("%.200s line %d: Missing argument.",
filename, linenum);
+ goto out;
+ }
remotefwd = (opcode == oRemoteForward);
dynamicfwd = (opcode == oDynamicForward);
if (!dynamicfwd) {
- arg2 = strdelim(&s);
+ arg2 = argv_next(&ac, &av);
if (arg2 == NULL || *arg2 == '\0') {
if (remotefwd)
dynamicfwd = 1;
- else
- fatal("%.200s line %d: Missing target "
+ else {
+ error("%.200s line %d: Missing target "
"argument.", filename, linenum);
+ goto out;
+ }
} else {
/* construct a string for parse_forward */
snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
@@ -1373,9 +1541,11 @@ parse_keytypes:
if (dynamicfwd)
strlcpy(fwdarg, arg, sizeof(fwdarg));
- if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0)
- fatal("%.200s line %d: Bad forwarding specification.",
+ if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) {
+ error("%.200s line %d: Bad forwarding specification.",
filename, linenum);
+ goto out;
+ }
if (*activep) {
if (remotefwd) {
@@ -1386,19 +1556,73 @@ parse_keytypes:
}
break;
+ case oPermitRemoteOpen:
+ uintptr = &options->num_permitted_remote_opens;
+ cppptr = &options->permitted_remote_opens;
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: missing %s specification",
+ filename, linenum, lookup_opcode_name(opcode));
+ uvalue = *uintptr; /* modified later */
+ if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) {
+ if (*activep && uvalue == 0) {
+ *uintptr = 1;
+ *cppptr = xcalloc(1, sizeof(**cppptr));
+ (*cppptr)[0] = xstrdup(arg);
+ }
+ break;
+ }
+ while ((arg = argv_next(&ac, &av)) != NULL) {
+ arg2 = xstrdup(arg);
+ ch = '\0';
+ p = hpdelim2(&arg, &ch);
+ if (p == NULL || ch == '/') {
+ fatal("%s line %d: missing host in %s",
+ filename, linenum,
+ lookup_opcode_name(opcode));
+ }
+ p = cleanhostname(p);
+ /*
+ * don't want to use permitopen_port to avoid
+ * dependency on channels.[ch] here.
+ */
+ if (arg == NULL ||
+ (strcmp(arg, "*") != 0 && a2port(arg) <= 0)) {
+ fatal("%s line %d: bad port number in %s",
+ filename, linenum,
+ lookup_opcode_name(opcode));
+ }
+ if (*activep && uvalue == 0) {
+ opt_array_append(filename, linenum,
+ lookup_opcode_name(opcode),
+ cppptr, uintptr, arg2);
+ }
+ free(arg2);
+ }
+ break;
+
case oClearAllForwardings:
intptr = &options->clear_forwardings;
goto parse_flag;
case oHost:
- if (cmdline)
- fatal("Host directive not supported as a command-line "
+ if (cmdline) {
+ error("Host directive not supported as a command-line "
"option");
+ goto out;
+ }
*activep = 0;
arg2 = NULL;
- while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
- if ((flags & SSHCONF_NEVERMATCH) != 0)
+ while ((arg = argv_next(&ac, &av)) != NULL) {
+ if (*arg == '\0') {
+ error("%s line %d: keyword %s empty argument",
+ filename, linenum, keyword);
+ goto out;
+ }
+ if ((flags & SSHCONF_NEVERMATCH) != 0) {
+ argv_consume(&ac);
break;
+ }
negated = *arg == '!';
if (negated)
arg++;
@@ -1409,6 +1633,7 @@ parse_keytypes:
"for %.100s", filename, linenum,
arg);
*activep = 0;
+ argv_consume(&ac);
break;
}
if (!*activep)
@@ -1419,27 +1644,40 @@ parse_keytypes:
if (*activep)
debug("%.200s line %d: Applying options for %.100s",
filename, linenum, arg2);
- /* Avoid garbage check below, as strdelim is done. */
- return 0;
+ break;
case oMatch:
- if (cmdline)
- fatal("Host directive not supported as a command-line "
+ if (cmdline) {
+ error("Host directive not supported as a command-line "
"option");
- value = match_cfg_line(options, &s, pw, host, original_host,
+ goto out;
+ }
+ value = match_cfg_line(options, &str, pw, host, original_host,
flags & SSHCONF_FINAL, want_final_pass,
filename, linenum);
- if (value < 0)
- fatal("%.200s line %d: Bad Match condition", filename,
+ if (value < 0) {
+ error("%.200s line %d: Bad Match condition", filename,
linenum);
+ goto out;
+ }
*activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
+ /*
+ * If match_cfg_line() didn't consume all its arguments then
+ * arrange for the extra arguments check below to fail.
+ */
+
+ if (str == NULL || *str == '\0')
+ argv_consume(&ac);
break;
case oEscapeChar:
intptr = &options->escape_char;
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ error("%.200s line %d: Missing argument.",
+ filename, linenum);
+ goto out;
+ }
if (strcmp(arg, "none") == 0)
value = SSH_ESCAPECHAR_NONE;
else if (arg[1] == '\0')
@@ -1448,10 +1686,9 @@ parse_keytypes:
(u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
value = (u_char) arg[1] & 31;
else {
- fatal("%.200s line %d: Bad escape character.",
+ error("%.200s line %d: Bad escape character.",
filename, linenum);
- /* NOTREACHED */
- value = 0; /* Avoid compiler warning. */
+ goto out;
}
if (*activep && *intptr == -1)
*intptr = value;
@@ -1479,10 +1716,12 @@ parse_keytypes:
goto parse_int;
case oSendEnv:
- while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
- if (strchr(arg, '=') != NULL)
- fatal("%s line %d: Invalid environment name.",
+ while ((arg = argv_next(&ac, &av)) != NULL) {
+ if (*arg == '\0' || strchr(arg, '=') != NULL) {
+ error("%s line %d: Invalid environment name.",
filename, linenum);
+ goto out;
+ }
if (!*activep)
continue;
if (*arg == '-') {
@@ -1491,9 +1730,11 @@ parse_keytypes:
continue;
} else {
/* Adding an env var */
- if (options->num_send_env >= INT_MAX)
- fatal("%s line %d: too many send env.",
+ if (options->num_send_env >= INT_MAX) {
+ error("%s line %d: too many send env.",
filename, linenum);
+ goto out;
+ }
options->send_env = xrecallocarray(
options->send_env, options->num_send_env,
options->num_send_env + 1,
@@ -1506,16 +1747,20 @@ parse_keytypes:
case oSetEnv:
value = options->num_setenv;
- while ((arg = strdelimw(&s)) != NULL && *arg != '\0') {
- if (strchr(arg, '=') == NULL)
- fatal("%s line %d: Invalid SetEnv.",
+ while ((arg = argv_next(&ac, &av)) != NULL) {
+ if (strchr(arg, '=') == NULL) {
+ error("%s line %d: Invalid SetEnv.",
filename, linenum);
+ goto out;
+ }
if (!*activep || value != 0)
continue;
/* Adding a setenv var */
- if (options->num_setenv >= INT_MAX)
- fatal("%s line %d: too many SetEnv.",
+ if (options->num_setenv >= INT_MAX) {
+ error("%s line %d: too many SetEnv.",
filename, linenum);
+ goto out;
+ }
options->setenv = xrecallocarray(
options->setenv, options->num_setenv,
options->num_setenv + 1, sizeof(*options->setenv));
@@ -1535,10 +1780,12 @@ parse_keytypes:
case oControlPersist:
/* no/false/yes/true, or a time spec */
intptr = &options->control_persist;
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing ControlPersist"
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ error("%.200s line %d: Missing ControlPersist"
" argument.", filename, linenum);
+ goto out;
+ }
value = 0;
value2 = 0; /* timeout */
if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
@@ -1547,9 +1794,11 @@ parse_keytypes:
value = 1;
else if ((value2 = convtime(arg)) >= 0)
value = 1;
- else
- fatal("%.200s line %d: Bad ControlPersist argument.",
+ else {
+ error("%.200s line %d: Bad ControlPersist argument.",
filename, linenum);
+ goto out;
+ }
if (*activep && *intptr == -1) {
*intptr = value;
options->control_persist_timeout = value2;
@@ -1566,13 +1815,19 @@ parse_keytypes:
goto parse_multistate;
case oTunnelDevice:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename, linenum);
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ error("%.200s line %d: Missing argument.",
+ filename, linenum);
+ goto out;
+ }
value = a2tun(arg, &value2);
- if (value == SSH_TUNID_ERR)
- fatal("%.200s line %d: Bad tun device.", filename, linenum);
- if (*activep) {
+ if (value == SSH_TUNID_ERR) {
+ error("%.200s line %d: Bad tun device.",
+ filename, linenum);
+ goto out;
+ }
+ if (*activep && options->tun_local == -1) {
options->tun_local = value;
options->tun_remote = value2;
}
@@ -1595,11 +1850,18 @@ parse_keytypes:
goto parse_flag;
case oInclude:
- if (cmdline)
- fatal("Include directive not supported as a "
+ if (cmdline) {
+ error("Include directive not supported as a "
"command-line option");
+ goto out;
+ }
value = 0;
- while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+ while ((arg = argv_next(&ac, &av)) != NULL) {
+ if (*arg == '\0') {
+ error("%s line %d: keyword %s empty argument",
+ filename, linenum, keyword);
+ goto out;
+ }
/*
* Ensure all paths are anchored. User configuration
* files may begin with '~/' but system configurations
@@ -1607,9 +1869,11 @@ parse_keytypes:
* as living in ~/.ssh for user configurations or
* /etc/ssh for system ones.
*/
- if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0)
- fatal("%.200s line %d: bad include path %s.",
+ if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) {
+ error("%.200s line %d: bad include path %s.",
filename, linenum, arg);
+ goto out;
+ }
if (!path_absolute(arg) && *arg != '~') {
xasprintf(&arg2, "%s/%s",
(flags & SSHCONF_USERCONF) ?
@@ -1623,9 +1887,11 @@ parse_keytypes:
"files",filename, linenum, arg2);
free(arg2);
continue;
- } else if (r != 0)
- fatal("%.200s line %d: glob failed for %s.",
+ } else if (r != 0) {
+ error("%.200s line %d: glob failed for %s.",
filename, linenum, arg2);
+ goto out;
+ }
free(arg2);
oactive = *activep;
for (i = 0; i < gl.gl_pathc; i++) {
@@ -1639,9 +1905,11 @@ parse_keytypes:
(oactive ? 0 : SSHCONF_NEVERMATCH),
activep, want_final_pass, depth + 1);
if (r != 1 && errno != ENOENT) {
- fatal("Can't open user config file "
+ error("Can't open user config file "
"%.100s: %.100s", gl.gl_pathv[i],
strerror(errno));
+ globfree(&gl);
+ goto out;
}
/*
* don't let Match in includes clobber the
@@ -1654,21 +1922,25 @@ parse_keytypes:
globfree(&gl);
}
if (value != 0)
- return value;
+ ret = value;
break;
case oIPQoS:
- arg = strdelim(&s);
- if ((value = parse_ipqos(arg)) == -1)
- fatal("%s line %d: Bad IPQoS value: %s",
+ arg = argv_next(&ac, &av);
+ if ((value = parse_ipqos(arg)) == -1) {
+ error("%s line %d: Bad IPQoS value: %s",
filename, linenum, arg);
- arg = strdelim(&s);
+ goto out;
+ }
+ arg = argv_next(&ac, &av);
if (arg == NULL)
value2 = value;
- else if ((value2 = parse_ipqos(arg)) == -1)
- fatal("%s line %d: Bad IPQoS value: %s",
+ else if ((value2 = parse_ipqos(arg)) == -1) {
+ error("%s line %d: Bad IPQoS value: %s",
filename, linenum, arg);
- if (*activep) {
+ goto out;
+ }
+ if (*activep && options->ip_qos_interactive == -1) {
options->ip_qos_interactive = value;
options->ip_qos_bulk = value2;
}
@@ -1679,6 +1951,19 @@ parse_keytypes:
multistate_ptr = multistate_requesttty;
goto parse_multistate;
+ case oSessionType:
+ intptr = &options->session_type;
+ multistate_ptr = multistate_sessiontype;
+ goto parse_multistate;
+
+ case oStdinNull:
+ intptr = &options->stdin_null;
+ goto parse_flag;
+
+ case oForkAfterAuthentication:
+ intptr = &options->fork_after_authentication;
+ goto parse_flag;
+
case oIgnoreUnknown:
charptr = &options->ignored_unknown;
goto parse_string;
@@ -1689,16 +1974,36 @@ parse_keytypes:
case oCanonicalDomains:
value = options->num_canonical_domains != 0;
- while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+ i = 0;
+ while ((arg = argv_next(&ac, &av)) != NULL) {
+ if (*arg == '\0') {
+ error("%s line %d: keyword %s empty argument",
+ filename, linenum, keyword);
+ goto out;
+ }
+ /* Allow "none" only in first position */
+ if (strcasecmp(arg, "none") == 0) {
+ if (i > 0 || ac > 0) {
+ error("%s line %d: keyword %s \"none\" "
+ "argument must appear alone.",
+ filename, linenum, keyword);
+ goto out;
+ }
+ }
+ i++;
if (!valid_domain(arg, 1, &errstr)) {
- fatal("%s line %d: %s", filename, linenum,
+ error("%s line %d: %s", filename, linenum,
errstr);
+ goto out;
}
if (!*activep || value)
continue;
- if (options->num_canonical_domains >= MAX_CANON_DOMAINS)
- fatal("%s line %d: too many hostname suffixes.",
+ if (options->num_canonical_domains >=
+ MAX_CANON_DOMAINS) {
+ error("%s line %d: too many hostname suffixes.",
filename, linenum);
+ goto out;
+ }
options->canonical_domains[
options->num_canonical_domains++] = xstrdup(arg);
}
@@ -1706,26 +2011,43 @@ parse_keytypes:
case oCanonicalizePermittedCNAMEs:
value = options->num_permitted_cnames != 0;
- while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
- /* Either '*' for everything or 'list:list' */
- if (strcmp(arg, "*") == 0)
+ i = 0;
+ while ((arg = argv_next(&ac, &av)) != NULL) {
+ /*
+ * Either 'none' (only in first position), '*' for
+ * everything or 'list:list'
+ */
+ if (strcasecmp(arg, "none") == 0) {
+ if (i > 0 || ac > 0) {
+ error("%s line %d: keyword %s \"none\" "
+ "argument must appear alone.",
+ filename, linenum, keyword);
+ goto out;
+ }
+ arg2 = "";
+ } else if (strcmp(arg, "*") == 0) {
arg2 = arg;
- else {
+ } else {
lowercase(arg);
if ((arg2 = strchr(arg, ':')) == NULL ||
arg2[1] == '\0') {
- fatal("%s line %d: "
+ error("%s line %d: "
"Invalid permitted CNAME \"%s\"",
filename, linenum, arg);
+ goto out;
}
*arg2 = '\0';
arg2++;
}
+ i++;
if (!*activep || value)
continue;
- if (options->num_permitted_cnames >= MAX_CANON_DOMAINS)
- fatal("%s line %d: too many permitted CNAMEs.",
+ if (options->num_permitted_cnames >=
+ MAX_CANON_DOMAINS) {
+ error("%s line %d: too many permitted CNAMEs.",
filename, linenum);
+ goto out;
+ }
cname = options->permitted_cnames +
options->num_permitted_cnames++;
cname->source_list = xstrdup(arg);
@@ -1747,13 +2069,18 @@ parse_keytypes:
goto parse_flag;
case oStreamLocalBindMask:
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum);
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ error("%.200s line %d: Missing StreamLocalBindMask "
+ "argument.", filename, linenum);
+ goto out;
+ }
/* Parse mode in octal format */
value = strtol(arg, &endofnumber, 8);
- if (arg == endofnumber || value < 0 || value > 0777)
- fatal("%.200s line %d: Bad mask.", filename, linenum);
+ if (arg == endofnumber || value < 0 || value > 0777) {
+ error("%.200s line %d: Bad mask.", filename, linenum);
+ goto out;
+ }
options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
break;
@@ -1767,13 +2094,17 @@ parse_keytypes:
case oFingerprintHash:
intptr = &options->fingerprint_hash;
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.",
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ error("%.200s line %d: Missing argument.",
filename, linenum);
- if ((value = ssh_digest_alg_by_name(arg)) == -1)
- fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
+ goto out;
+ }
+ if ((value = ssh_digest_alg_by_name(arg)) == -1) {
+ error("%.200s line %d: Invalid hash algorithm \"%s\".",
filename, linenum, arg);
+ goto out;
+ }
if (*activep && *intptr == -1)
*intptr = value;
break;
@@ -1783,30 +2114,69 @@ parse_keytypes:
multistate_ptr = multistate_yesnoask;
goto parse_multistate;
- case oHostbasedKeyTypes:
- charptr = &options->hostbased_key_types;
- goto parse_keytypes;
+ case oHostbasedAcceptedAlgorithms:
+ charptr = &options->hostbased_accepted_algos;
+ goto parse_pubkey_algos;
- case oPubkeyAcceptedKeyTypes:
- charptr = &options->pubkey_key_types;
- goto parse_keytypes;
+ case oPubkeyAcceptedAlgorithms:
+ charptr = &options->pubkey_accepted_algos;
+ goto parse_pubkey_algos;
case oAddKeysToAgent:
- intptr = &options->add_keys_to_agent;
- multistate_ptr = multistate_yesnoaskconfirm;
- goto parse_multistate;
+ arg = argv_next(&ac, &av);
+ arg2 = argv_next(&ac, &av);
+ value = parse_multistate_value(arg, filename, linenum,
+ multistate_yesnoaskconfirm);
+ value2 = 0; /* unlimited lifespan by default */
+ if (value == 3 && arg2 != NULL) {
+ /* allow "AddKeysToAgent confirm 5m" */
+ if ((value2 = convtime(arg2)) == -1 ||
+ value2 > INT_MAX) {
+ error("%s line %d: invalid time value.",
+ filename, linenum);
+ goto out;
+ }
+ } else if (value == -1 && arg2 == NULL) {
+ if ((value2 = convtime(arg)) == -1 ||
+ value2 > INT_MAX) {
+ error("%s line %d: unsupported option",
+ filename, linenum);
+ goto out;
+ }
+ value = 1; /* yes */
+ } else if (value == -1 || arg2 != NULL) {
+ error("%s line %d: unsupported option",
+ filename, linenum);
+ goto out;
+ }
+ if (*activep && options->add_keys_to_agent == -1) {
+ options->add_keys_to_agent = value;
+ options->add_keys_to_agent_lifespan = value2;
+ }
+ break;
case oIdentityAgent:
charptr = &options->identity_agent;
- arg = strdelim(&s);
- if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.",
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ error("%.200s line %d: Missing argument.",
filename, linenum);
+ goto out;
+ }
parse_agent_path:
/* Extra validation if the string represents an env var. */
- if (arg[0] == '$' && !valid_env_name(arg + 1)) {
- fatal("%.200s line %d: Invalid environment name %s.",
+ if ((arg2 = dollar_expand(&r, arg)) == NULL || r) {
+ error("%.200s line %d: Invalid environment expansion "
+ "%s.", filename, linenum, arg);
+ goto out;
+ }
+ free(arg2);
+ /* check for legacy environment format */
+ if (arg[0] == '$' && arg[1] != '{' &&
+ !valid_env_name(arg + 1)) {
+ error("%.200s line %d: Invalid environment name %s.",
filename, linenum, arg);
+ goto out;
}
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
@@ -1815,23 +2185,33 @@ parse_keytypes:
case oDeprecated:
debug("%s line %d: Deprecated option \"%s\"",
filename, linenum, keyword);
- return 0;
+ argv_consume(&ac);
+ break;
case oUnsupported:
error("%s line %d: Unsupported option \"%s\"",
filename, linenum, keyword);
- return 0;
+ argv_consume(&ac);
+ break;
default:
- fatal("%s: Unimplemented opcode %d", __func__, opcode);
+ error("%s line %d: Unimplemented opcode %d",
+ filename, linenum, opcode);
+ goto out;
}
/* Check that there is no garbage at end of line. */
- if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
- fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
- filename, linenum, arg);
+ if (ac > 0) {
+ error("%.200s line %d: keyword %s extra arguments "
+ "at end of line", filename, linenum, keyword);
+ goto out;
}
- return 0;
+
+ /* success */
+ ret = 0;
+ out:
+ argv_free(oav, oac);
+ return ret;
}
/*
@@ -1888,6 +2268,11 @@ read_config_file_depth(const char *filename, struct passwd *pw,
while (getline(&line, &linesize, f) != -1) {
/* Update line number counter. */
linenum++;
+ /*
+ * Trim out comments and strip whitespace.
+ * NB - preserve newlines, they are needed to reproduce
+ * line numbers later for error messages.
+ */
if (process_config_line_depth(options, pw, host, original_host,
line, filename, linenum, activep, flags, want_final_pass,
depth) != 0)
@@ -1909,6 +2294,20 @@ option_clear_or_none(const char *o)
}
/*
+ * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise.
+ * Allowed to be called on non-final configuration.
+ */
+int
+config_has_permitted_cnames(Options *options)
+{
+ if (options->num_permitted_cnames == 1 &&
+ strcasecmp(options->permitted_cnames[0].source_list, "none") == 0 &&
+ strcmp(options->permitted_cnames[0].target_list, "") == 0)
+ return 0;
+ return options->num_permitted_cnames > 0;
+}
+
+/*
* Initializes options to special values that indicate that they have not yet
* been set. Read_config_file will only set options with this value. Options
* are processed in the following order: command line, user config file,
@@ -1933,7 +2332,6 @@ initialize_options(Options * options)
options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
options->fwd_opts.streamlocal_bind_unlink = -1;
options->pubkey_authentication = -1;
- options->challenge_response_authentication = -1;
options->gss_authentication = -1;
options->gss_deleg_creds = -1;
options->password_authentication = -1;
@@ -1956,7 +2354,9 @@ initialize_options(Options * options)
options->hostkeyalgorithms = NULL;
options->ca_sign_algorithms = NULL;
options->num_identity_files = 0;
+ memset(options->identity_keys, 0, sizeof(options->identity_keys));
options->num_certificate_files = 0;
+ memset(options->certificates, 0, sizeof(options->certificates));
options->hostname = NULL;
options->host_key_alias = NULL;
options->proxy_command = NULL;
@@ -1972,8 +2372,12 @@ initialize_options(Options * options)
options->num_local_forwards = 0;
options->remote_forwards = NULL;
options->num_remote_forwards = 0;
+ options->permitted_remote_opens = NULL;
+ options->num_permitted_remote_opens = 0;
options->log_facility = SYSLOG_FACILITY_NOT_SET;
options->log_level = SYSLOG_LEVEL_NOT_SET;
+ options->num_log_verbose = 0;
+ options->log_verbose = NULL;
options->preferred_authentications = NULL;
options->bind_address = NULL;
options->bind_interface = NULL;
@@ -2003,11 +2407,15 @@ initialize_options(Options * options)
options->permit_local_command = -1;
options->remote_command = NULL;
options->add_keys_to_agent = -1;
+ options->add_keys_to_agent_lifespan = -1;
options->identity_agent = NULL;
options->visual_host_key = -1;
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -1;
options->request_tty = -1;
+ options->session_type = -1;
+ options->stdin_null = -1;
+ options->fork_after_authentication = -1;
options->proxy_use_fdpass = -1;
options->ignored_unknown = NULL;
options->num_canonical_domains = 0;
@@ -2018,8 +2426,9 @@ initialize_options(Options * options)
options->revoked_host_keys = NULL;
options->fingerprint_hash = -1;
options->update_hostkeys = -1;
- options->hostbased_key_types = NULL;
- options->pubkey_key_types = NULL;
+ options->hostbased_accepted_algos = NULL;
+ options->pubkey_accepted_algos = NULL;
+ options->known_hosts_command = NULL;
}
/*
@@ -2041,12 +2450,12 @@ fill_default_options_for_canonicalization(Options *options)
* Called after processing other sources of option data, this fills those
* options for which no value has been specified with their default values.
*/
-void
+int
fill_default_options(Options * options)
{
char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
- int r;
+ int ret = 0, r;
if (options->forward_agent == -1)
options->forward_agent = 0;
@@ -2070,7 +2479,7 @@ fill_default_options(Options * options)
clear_forwardings(options);
if (options->xauth_location == NULL)
- options->xauth_location = _PATH_XAUTH;
+ options->xauth_location = xstrdup(_PATH_XAUTH);
if (options->fwd_opts.gateway_ports == -1)
options->fwd_opts.gateway_ports = 0;
if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
@@ -2079,8 +2488,6 @@ fill_default_options(Options * options)
options->fwd_opts.streamlocal_bind_unlink = 0;
if (options->pubkey_authentication == -1)
options->pubkey_authentication = 1;
- if (options->challenge_response_authentication == -1)
- options->challenge_response_authentication = 1;
if (options->gss_authentication == -1)
options->gss_authentication = 0;
if (options->gss_deleg_creds == -1)
@@ -2094,7 +2501,7 @@ fill_default_options(Options * options)
if (options->batch_mode == -1)
options->batch_mode = 0;
if (options->check_host_ip == -1)
- options->check_host_ip = 1;
+ options->check_host_ip = 0;
if (options->strict_host_key_checking == -1)
options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
if (options->compression == -1)
@@ -2110,8 +2517,10 @@ fill_default_options(Options * options)
if (options->number_of_password_prompts == -1)
options->number_of_password_prompts = 3;
/* options->hostkeyalgorithms, default set in myproposals.h */
- if (options->add_keys_to_agent == -1)
+ if (options->add_keys_to_agent == -1) {
options->add_keys_to_agent = 0;
+ options->add_keys_to_agent_lifespan = 0;
+ }
if (options->num_identity_files == 0) {
add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
@@ -2134,8 +2543,15 @@ fill_default_options(Options * options)
options->system_hostfiles[options->num_system_hostfiles++] =
xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
}
- if (options->update_hostkeys == -1)
+ if (options->update_hostkeys == -1) {
+ if (options->verify_host_key_dns <= 0 &&
+ (options->num_user_hostfiles == 0 ||
+ (options->num_user_hostfiles == 1 && strcmp(options->
+ user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0)))
+ options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES;
+ else
options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO;
+ }
if (options->num_user_hostfiles == 0) {
options->user_hostfiles[options->num_user_hostfiles++] =
xstrdup(_PATH_SSH_USER_HOSTFILE);
@@ -2186,6 +2602,12 @@ fill_default_options(Options * options)
options->ip_qos_bulk = IPTOS_DSCP_CS1;
if (options->request_tty == -1)
options->request_tty = REQUEST_TTY_AUTO;
+ if (options->session_type == -1)
+ options->session_type = SESSION_TYPE_DEFAULT;
+ if (options->stdin_null == -1)
+ options->stdin_null = 0;
+ if (options->fork_after_authentication == -1)
+ options->fork_after_authentication = 0;
if (options->proxy_use_fdpass == -1)
options->proxy_use_fdpass = 0;
if (options->canonicalize_max_dots == -1)
@@ -2211,34 +2633,26 @@ fill_default_options(Options * options)
all_key = sshkey_alg_list(0, 0, 1, ',');
all_sig = sshkey_alg_list(0, 1, 1, ',');
/* remove unsupported algos from default lists */
- def_cipher = match_filter_whitelist(KEX_CLIENT_ENCRYPT, all_cipher);
- def_mac = match_filter_whitelist(KEX_CLIENT_MAC, all_mac);
- def_kex = match_filter_whitelist(KEX_CLIENT_KEX, all_kex);
- def_key = match_filter_whitelist(KEX_DEFAULT_PK_ALG, all_key);
- def_sig = match_filter_whitelist(SSH_ALLOWED_CA_SIGALGS, all_sig);
+ def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
+ def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
+ def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
+ def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
+ def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
#define ASSEMBLE(what, defaults, all) \
do { \
if ((r = kex_assemble_names(&options->what, \
- defaults, all)) != 0) \
- fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \
+ defaults, all)) != 0) { \
+ error_fr(r, "%s", #what); \
+ goto fail; \
+ } \
} while (0)
ASSEMBLE(ciphers, def_cipher, all_cipher);
ASSEMBLE(macs, def_mac, all_mac);
ASSEMBLE(kex_algorithms, def_kex, all_kex);
- ASSEMBLE(hostbased_key_types, def_key, all_key);
- ASSEMBLE(pubkey_key_types, def_key, all_key);
+ ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
+ ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
#undef ASSEMBLE
- free(all_cipher);
- free(all_mac);
- free(all_kex);
- free(all_key);
- free(all_sig);
- free(def_cipher);
- free(def_mac);
- free(def_kex);
- kex_default_pk_alg_filtered = def_key; /* save for later use */
- free(def_sig);
#define CLEAR_ON_NONE(v) \
do { \
@@ -2254,17 +2668,124 @@ fill_default_options(Options * options)
CLEAR_ON_NONE(options->revoked_host_keys);
CLEAR_ON_NONE(options->pkcs11_provider);
CLEAR_ON_NONE(options->sk_provider);
+ CLEAR_ON_NONE(options->known_hosts_command);
if (options->jump_host != NULL &&
strcmp(options->jump_host, "none") == 0 &&
options->jump_port == 0 && options->jump_user == NULL) {
free(options->jump_host);
options->jump_host = NULL;
}
+ if (options->num_permitted_cnames == 1 &&
+ !config_has_permitted_cnames(options)) {
+ /* clean up CanonicalizePermittedCNAMEs=none */
+ free(options->permitted_cnames[0].source_list);
+ free(options->permitted_cnames[0].target_list);
+ memset(options->permitted_cnames, '\0',
+ sizeof(*options->permitted_cnames));
+ options->num_permitted_cnames = 0;
+ }
/* options->identity_agent distinguishes NULL from 'none' */
/* options->user will be set in the main program if appropriate */
/* options->hostname will be set in the main program if appropriate */
/* options->host_key_alias should not be set by default */
/* options->preferred_authentications will be set in ssh */
+
+ /* success */
+ ret = 0;
+ fail:
+ free(all_cipher);
+ free(all_mac);
+ free(all_kex);
+ free(all_key);
+ free(all_sig);
+ free(def_cipher);
+ free(def_mac);
+ free(def_kex);
+ free(def_key);
+ free(def_sig);
+ return ret;
+}
+
+void
+free_options(Options *o)
+{
+ int i;
+
+ if (o == NULL)
+ return;
+
+#define FREE_ARRAY(type, n, a) \
+ do { \
+ type _i; \
+ for (_i = 0; _i < (n); _i++) \
+ free((a)[_i]); \
+ } while (0)
+
+ free(o->forward_agent_sock_path);
+ free(o->xauth_location);
+ FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose);
+ free(o->log_verbose);
+ free(o->ciphers);
+ free(o->macs);
+ free(o->hostkeyalgorithms);
+ free(o->kex_algorithms);
+ free(o->ca_sign_algorithms);
+ free(o->hostname);
+ free(o->host_key_alias);
+ free(o->proxy_command);
+ free(o->user);
+ FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles);
+ FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles);
+ free(o->preferred_authentications);
+ free(o->bind_address);
+ free(o->bind_interface);
+ free(o->pkcs11_provider);
+ free(o->sk_provider);
+ for (i = 0; i < o->num_identity_files; i++) {
+ free(o->identity_files[i]);
+ sshkey_free(o->identity_keys[i]);
+ }
+ for (i = 0; i < o->num_certificate_files; i++) {
+ free(o->certificate_files[i]);
+ sshkey_free(o->certificates[i]);
+ }
+ free(o->identity_agent);
+ for (i = 0; i < o->num_local_forwards; i++) {
+ free(o->local_forwards[i].listen_host);
+ free(o->local_forwards[i].listen_path);
+ free(o->local_forwards[i].connect_host);
+ free(o->local_forwards[i].connect_path);
+ }
+ free(o->local_forwards);
+ for (i = 0; i < o->num_remote_forwards; i++) {
+ free(o->remote_forwards[i].listen_host);
+ free(o->remote_forwards[i].listen_path);
+ free(o->remote_forwards[i].connect_host);
+ free(o->remote_forwards[i].connect_path);
+ }
+ free(o->remote_forwards);
+ free(o->stdio_forward_host);
+ FREE_ARRAY(int, o->num_send_env, o->send_env);
+ free(o->send_env);
+ FREE_ARRAY(int, o->num_setenv, o->setenv);
+ free(o->setenv);
+ free(o->control_path);
+ free(o->local_command);
+ free(o->remote_command);
+ FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains);
+ for (i = 0; i < o->num_permitted_cnames; i++) {
+ free(o->permitted_cnames[i].source_list);
+ free(o->permitted_cnames[i].target_list);
+ }
+ free(o->revoked_host_keys);
+ free(o->hostbased_accepted_algos);
+ free(o->pubkey_accepted_algos);
+ free(o->jump_user);
+ free(o->jump_host);
+ free(o->jump_extra);
+ free(o->ignored_unknown);
+ explicit_bzero(o, sizeof(*o));
+#undef FREE_ARRAY
}
struct fwdarg {
@@ -2350,12 +2871,19 @@ parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remo
{
struct fwdarg fwdargs[4];
char *p, *cp;
- int i;
+ int i, err;
memset(fwd, 0, sizeof(*fwd));
memset(fwdargs, 0, sizeof(fwdargs));
- cp = p = xstrdup(fwdspec);
+ /*
+ * We expand environment variables before checking if we think they're
+ * paths so that if ${VAR} expands to a fully qualified path it is
+ * treated as a path.
+ */
+ cp = p = dollar_expand(&err, fwdspec);
+ if (p == NULL || err)
+ return 0;
/* skip leading spaces */
while (isspace((u_char)*cp))
@@ -2451,7 +2979,10 @@ parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remo
if (fwd->connect_host != NULL &&
strlen(fwd->connect_host) >= NI_MAXHOST)
goto fail_free;
- /* XXX - if connecting to a remote socket, max sun len may not match this host */
+ /*
+ * XXX - if connecting to a remote socket, max sun len may not
+ * match this host
+ */
if (fwd->connect_path != NULL &&
strlen(fwd->connect_path) >= PATH_MAX_SUN)
goto fail_free;
@@ -2481,11 +3012,17 @@ parse_jump(const char *s, Options *o, int active)
{
char *orig, *sdup, *cp;
char *host = NULL, *user = NULL;
- int ret = -1, port = -1, first;
+ int r, ret = -1, port = -1, first;
active &= o->proxy_command == NULL && o->jump_host == NULL;
orig = sdup = xstrdup(s);
+
+ /* Remove comment and trailing whitespace */
+ if ((cp = strchr(orig, '#')) != NULL)
+ *cp = '\0';
+ rtrim(orig);
+
first = active;
do {
if (strcasecmp(s, "none") == 0)
@@ -2497,13 +3034,15 @@ parse_jump(const char *s, Options *o, int active)
if (first) {
/* First argument and configuration is active */
- if (parse_ssh_uri(cp, &user, &host, &port) == -1 ||
- parse_user_host_port(cp, &user, &host, &port) != 0)
+ r = parse_ssh_uri(cp, &user, &host, &port);
+ if (r == -1 || (r == 1 &&
+ parse_user_host_port(cp, &user, &host, &port) != 0))
goto out;
} else {
/* Subsequent argument or inactive configuration */
- if (parse_ssh_uri(cp, NULL, NULL, NULL) == -1 ||
- parse_user_host_port(cp, NULL, NULL, NULL) != 0)
+ r = parse_ssh_uri(cp, NULL, NULL, NULL);
+ if (r == -1 || (r == 1 &&
+ parse_user_host_port(cp, NULL, NULL, NULL) != 0))
goto out;
}
first = 0; /* only check syntax for subsequent hosts */
@@ -2536,12 +3075,27 @@ parse_jump(const char *s, Options *o, int active)
int
parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
{
- char *path;
- int r;
+ char *user = NULL, *host = NULL, *path = NULL;
+ int r, port;
- r = parse_uri("ssh", uri, userp, hostp, portp, &path);
+ r = parse_uri("ssh", uri, &user, &host, &port, &path);
if (r == 0 && path != NULL)
r = -1; /* path not allowed */
+ if (r == 0) {
+ if (userp != NULL) {
+ *userp = user;
+ user = NULL;
+ }
+ if (hostp != NULL) {
+ *hostp = host;
+ host = NULL;
+ }
+ if (portp != NULL)
+ *portp = port;
+ }
+ free(user);
+ free(host);
+ free(path);
return r;
}
@@ -2577,6 +3131,8 @@ fmt_intarg(OpCodes code, int val)
return fmt_multistate_int(val, multistate_tunnel);
case oRequestTTY:
return fmt_multistate_int(val, multistate_requesttty);
+ case oSessionType:
+ return fmt_multistate_int(val, multistate_sessiontype);
case oCanonicalizeHostname:
return fmt_multistate_int(val, multistate_canonicalizehostname);
case oAddKeysToAgent:
@@ -2641,6 +3197,8 @@ dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
u_int i;
printf("%s", lookup_opcode_name(code));
+ if (count == 0)
+ printf(" none");
for (i = 0; i < count; i++)
printf(" %s", vals[i]);
printf("\n");
@@ -2699,7 +3257,7 @@ dump_client_config(Options *o, const char *host)
all_key = sshkey_alg_list(0, 0, 1, ',');
if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(),
all_key)) != 0)
- fatal("%s: expand HostKeyAlgorithms: %s", __func__, ssh_err(r));
+ fatal_fr(r, "expand HostKeyAlgorithms");
free(all_key);
/* Most interesting options first: user, host, port */
@@ -2708,12 +3266,10 @@ dump_client_config(Options *o, const char *host)
dump_cfg_int(oPort, o->port);
/* Flag options */
- dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
dump_cfg_fmtint(oAddressFamily, o->address_family);
dump_cfg_fmtint(oBatchMode, o->batch_mode);
dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
- dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication);
dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
dump_cfg_fmtint(oCompression, o->compression);
dump_cfg_fmtint(oControlMaster, o->control_master);
@@ -2738,6 +3294,9 @@ dump_client_config(Options *o, const char *host)
dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
dump_cfg_fmtint(oRequestTTY, o->request_tty);
+ dump_cfg_fmtint(oSessionType, o->session_type);
+ dump_cfg_fmtint(oStdinNull, o->stdin_null);
+ dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication);
dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
@@ -2761,7 +3320,7 @@ dump_client_config(Options *o, const char *host)
dump_cfg_string(oControlPath, o->control_path);
dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
dump_cfg_string(oHostKeyAlias, o->host_key_alias);
- dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types);
+ dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
dump_cfg_string(oIdentityAgent, o->identity_agent);
dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
@@ -2776,9 +3335,10 @@ dump_client_config(Options *o, const char *host)
#endif
dump_cfg_string(oSecurityKeyProvider, o->sk_provider);
dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
- dump_cfg_string(oPubkeyAcceptedKeyTypes, o->pubkey_key_types);
+ dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
dump_cfg_string(oXAuthLocation, o->xauth_location);
+ dump_cfg_string(oKnownHostsCommand, o->known_hosts_command);
/* Forwards */
dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
@@ -2793,9 +3353,27 @@ dump_client_config(Options *o, const char *host)
dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
+ dump_cfg_strarray_oneline(oLogVerbose,
+ o->num_log_verbose, o->log_verbose);
/* Special cases */
+ /* PermitRemoteOpen */
+ if (o->num_permitted_remote_opens == 0)
+ printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen));
+ else
+ dump_cfg_strarray_oneline(oPermitRemoteOpen,
+ o->num_permitted_remote_opens, o->permitted_remote_opens);
+
+ /* AddKeysToAgent */
+ if (o->add_keys_to_agent_lifespan <= 0)
+ dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
+ else {
+ printf("addkeystoagent%s %d\n",
+ o->add_keys_to_agent == 3 ? " confirm" : "",
+ o->add_keys_to_agent_lifespan);
+ }
+
/* oForwardAgent */
if (o->forward_agent_sock_path == NULL)
dump_cfg_fmtint(oForwardAgent, o->forward_agent);
@@ -2821,14 +3399,14 @@ dump_client_config(Options *o, const char *host)
printf("\n");
/* oCanonicalizePermittedCNAMEs */
- if ( o->num_permitted_cnames > 0) {
- printf("canonicalizePermittedcnames");
- for (i = 0; i < o->num_permitted_cnames; i++) {
- printf(" %s:%s", o->permitted_cnames[i].source_list,
- o->permitted_cnames[i].target_list);
- }
- printf("\n");
+ printf("canonicalizePermittedcnames");
+ if (o->num_permitted_cnames == 0)
+ printf(" none");
+ for (i = 0; i < o->num_permitted_cnames; i++) {
+ printf(" %s:%s", o->permitted_cnames[i].source_list,
+ o->permitted_cnames[i].target_list);
}
+ printf("\n");
/* oControlPersist */
if (o->control_persist == 0 || o->control_persist_timeout == 0)
diff --git a/readconf.h b/readconf.h
index e143a1082..f24719f98 100644
--- a/readconf.h
+++ b/readconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.h,v 1.133 2020/04/03 02:27:12 dtucker Exp $ */
+/* $OpenBSD: readconf.h,v 1.145 2021/09/15 06:56:01 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -38,8 +38,6 @@ typedef struct {
struct ForwardOptions fwd_opts; /* forwarding options */
int pubkey_authentication; /* Try ssh2 pubkey authentication. */
int hostbased_authentication; /* ssh2's rhosts_rsa */
- int challenge_response_authentication;
- /* Try S/Key or TIS, authentication. */
int gss_authentication; /* Try GSS authentication */
int gss_deleg_creds; /* Delegate GSS credentials */
int password_authentication; /* Try password
@@ -55,7 +53,8 @@ typedef struct {
int ip_qos_bulk; /* IP ToS/DSCP/class for bulk traffic */
SyslogFacility log_facility; /* Facility for system logging. */
LogLevel log_level; /* Level for logging. */
-
+ u_int num_log_verbose; /* Verbose log overrides */
+ char **log_verbose;
int port; /* Port to connect. */
int address_family;
int connection_attempts; /* Max attempts (seconds) before
@@ -97,6 +96,7 @@ typedef struct {
struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES];
int add_keys_to_agent;
+ int add_keys_to_agent_lifespan;
char *identity_agent; /* Optional path to ssh-agent socket */
/* Local TCP/IP forward requests. */
@@ -108,6 +108,10 @@ typedef struct {
struct Forward *remote_forwards;
int clear_forwardings;
+ /* Restrict remote dynamic forwarding */
+ char **permitted_remote_opens;
+ u_int num_permitted_remote_opens;
+
/* stdio forwarding (-W) host and port */
char *stdio_forward_host;
int stdio_forward_port;
@@ -142,6 +146,9 @@ typedef struct {
int visual_host_key;
int request_tty;
+ int session_type;
+ int stdin_null;
+ int fork_after_authentication;
int proxy_use_fdpass;
@@ -159,14 +166,16 @@ typedef struct {
int update_hostkeys; /* one of SSH_UPDATE_HOSTKEYS_* */
- char *hostbased_key_types;
- char *pubkey_key_types;
+ char *hostbased_accepted_algos;
+ char *pubkey_accepted_algos;
char *jump_user;
char *jump_host;
int jump_port;
char *jump_extra;
+ char *known_hosts_command;
+
char *ignored_unknown; /* Pattern list of unknown tokens to ignore */
} Options;
@@ -185,6 +194,10 @@ typedef struct {
#define REQUEST_TTY_YES 2
#define REQUEST_TTY_FORCE 3
+#define SESSION_TYPE_NONE 0
+#define SESSION_TYPE_SUBSYSTEM 1
+#define SESSION_TYPE_DEFAULT 2
+
#define SSHCONF_CHECKPERM 1 /* check permissions on config file */
#define SSHCONF_USERCONF 2 /* user provided config file not system */
#define SSHCONF_FINAL 4 /* Final pass over config, after canon. */
@@ -203,8 +216,9 @@ const char *kex_default_pk_alg(void);
char *ssh_connection_hash(const char *thishost, const char *host,
const char *portstr, const char *user);
void initialize_options(Options *);
-void fill_default_options(Options *);
+int fill_default_options(Options *);
void fill_default_options_for_canonicalization(Options *);
+void free_options(Options *o);
int process_config_line(Options *, struct passwd *, const char *,
const char *, char *, const char *, int, int *, int);
int read_config_file(const char *, struct passwd *, const char *,
@@ -214,6 +228,7 @@ int parse_jump(const char *, Options *, int);
int parse_ssh_uri(const char *, char **, char **, int *);
int default_ssh_port(void);
int option_clear_or_none(const char *);
+int config_has_permitted_cnames(Options *);
void dump_client_config(Options *o, const char *host);
void add_local_forward(Options *, const struct Forward *);
diff --git a/readpass.c b/readpass.c
index 974d67f0b..39af25c88 100644
--- a/readpass.c
+++ b/readpass.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readpass.c,v 1.61 2020/01/23 07:10:22 dtucker Exp $ */
+/* $OpenBSD: readpass.c,v 1.69 2021/07/23 05:56:47 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
@@ -58,27 +58,27 @@ ssh_askpass(char *askpass, const char *msg, const char *env_hint)
void (*osigchld)(int);
if (fflush(stdout) != 0)
- error("%s: fflush: %s", __func__, strerror(errno));
+ error_f("fflush: %s", strerror(errno));
if (askpass == NULL)
fatal("internal error: askpass undefined");
if (pipe(p) == -1) {
- error("%s: pipe: %s", __func__, strerror(errno));
+ error_f("pipe: %s", strerror(errno));
return NULL;
}
osigchld = ssh_signal(SIGCHLD, SIG_DFL);
if ((pid = fork()) == -1) {
- error("%s: fork: %s", __func__, strerror(errno));
+ error_f("fork: %s", strerror(errno));
ssh_signal(SIGCHLD, osigchld);
return NULL;
}
if (pid == 0) {
close(p[0]);
if (dup2(p[1], STDOUT_FILENO) == -1)
- fatal("%s: dup2: %s", __func__, strerror(errno));
+ fatal_f("dup2: %s", strerror(errno));
if (env_hint != NULL)
setenv("SSH_ASKPASS_PROMPT", env_hint, 1);
execlp(askpass, askpass, msg, (char *)NULL);
- fatal("%s: exec(%s): %s", __func__, askpass, strerror(errno));
+ fatal_f("exec(%s): %s", askpass, strerror(errno));
}
close(p[1]);
@@ -117,21 +117,36 @@ ssh_askpass(char *askpass, const char *msg, const char *env_hint)
* Reads a passphrase from /dev/tty with echo turned off/on. Returns the
* passphrase (allocated with xmalloc). Exits if EOF is encountered. If
* RP_ALLOW_STDIN is set, the passphrase will be read from stdin if no
- * tty is available
+ * tty is or askpass program is available
*/
char *
read_passphrase(const char *prompt, int flags)
{
char cr = '\r', *askpass = NULL, *ret, buf[1024];
- int rppflags, use_askpass = 0, ttyfd;
+ int rppflags, ttyfd, use_askpass = 0, allow_askpass = 0;
const char *askpass_hint = NULL;
+ const char *s;
+
+ if ((s = getenv("DISPLAY")) != NULL)
+ allow_askpass = *s != '\0';
+ if ((s = getenv(SSH_ASKPASS_REQUIRE_ENV)) != NULL) {
+ if (strcasecmp(s, "force") == 0) {
+ use_askpass = 1;
+ allow_askpass = 1;
+ } else if (strcasecmp(s, "prefer") == 0)
+ use_askpass = allow_askpass;
+ else if (strcasecmp(s, "never") == 0)
+ allow_askpass = 0;
+ }
rppflags = (flags & RP_ECHO) ? RPP_ECHO_ON : RPP_ECHO_OFF;
- if (flags & RP_USE_ASKPASS)
+ if (use_askpass)
+ debug_f("requested to askpass");
+ else if (flags & RP_USE_ASKPASS)
use_askpass = 1;
else if (flags & RP_ALLOW_STDIN) {
if (!isatty(STDIN_FILENO)) {
- debug("read_passphrase: stdin is not a tty");
+ debug_f("stdin is not a tty");
use_askpass = 1;
}
} else {
@@ -147,16 +162,16 @@ read_passphrase(const char *prompt, int flags)
(void)write(ttyfd, &cr, 1);
close(ttyfd);
} else {
- debug("read_passphrase: can't open %s: %s", _PATH_TTY,
+ debug_f("can't open %s: %s", _PATH_TTY,
strerror(errno));
use_askpass = 1;
}
}
- if ((flags & RP_USE_ASKPASS) && getenv("DISPLAY") == NULL)
+ if ((flags & RP_USE_ASKPASS) && !allow_askpass)
return (flags & RP_ALLOW_EOF) ? NULL : xstrdup("");
- if (use_askpass && getenv("DISPLAY")) {
+ if (use_askpass && allow_askpass) {
if (getenv(SSH_ASKPASS_ENV))
askpass = getenv(SSH_ASKPASS_ENV);
else
@@ -207,6 +222,14 @@ ask_permission(const char *fmt, ...)
return (allowed);
}
+static void
+writemsg(const char *msg)
+{
+ (void)write(STDERR_FILENO, "\r", 1);
+ (void)write(STDERR_FILENO, msg, strlen(msg));
+ (void)write(STDERR_FILENO, "\r\n", 2);
+}
+
struct notifier_ctx {
pid_t pid;
void (*osigchld)(int);
@@ -217,66 +240,80 @@ notify_start(int force_askpass, const char *fmt, ...)
{
va_list args;
char *prompt = NULL;
- int devnull;
- pid_t pid;
- void (*osigchld)(int);
- const char *askpass;
- struct notifier_ctx *ret;
+ pid_t pid = -1;
+ void (*osigchld)(int) = NULL;
+ const char *askpass, *s;
+ struct notifier_ctx *ret = NULL;
va_start(args, fmt);
xvasprintf(&prompt, fmt, args);
va_end(args);
if (fflush(NULL) != 0)
- error("%s: fflush: %s", __func__, strerror(errno));
+ error_f("fflush: %s", strerror(errno));
if (!force_askpass && isatty(STDERR_FILENO)) {
- (void)write(STDERR_FILENO, "\r", 1);
- (void)write(STDERR_FILENO, prompt, strlen(prompt));
- (void)write(STDERR_FILENO, "\r\n", 2);
- free(prompt);
- return NULL;
+ writemsg(prompt);
+ goto out_ctx;
}
if ((askpass = getenv("SSH_ASKPASS")) == NULL)
askpass = _PATH_SSH_ASKPASS_DEFAULT;
- if (getenv("DISPLAY") == NULL || *askpass == '\0') {
- debug3("%s: cannot notify", __func__);
- free(prompt);
- return NULL;
+ if (*askpass == '\0') {
+ debug3_f("cannot notify: no askpass");
+ goto out;
+ }
+ if (getenv("DISPLAY") == NULL &&
+ ((s = getenv(SSH_ASKPASS_REQUIRE_ENV)) == NULL ||
+ strcmp(s, "force") != 0)) {
+ debug3_f("cannot notify: no display");
+ goto out;
}
osigchld = ssh_signal(SIGCHLD, SIG_DFL);
if ((pid = fork()) == -1) {
- error("%s: fork: %s", __func__, strerror(errno));
+ error_f("fork: %s", strerror(errno));
ssh_signal(SIGCHLD, osigchld);
free(prompt);
return NULL;
}
if (pid == 0) {
- if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1)
- fatal("%s: open %s", __func__, strerror(errno));
- if (dup2(devnull, STDIN_FILENO) == -1 ||
- dup2(devnull, STDOUT_FILENO) == -1)
- fatal("%s: dup2: %s", __func__, strerror(errno));
+ if (stdfd_devnull(1, 1, 0) == -1)
+ fatal_f("stdfd_devnull failed");
closefrom(STDERR_FILENO + 1);
setenv("SSH_ASKPASS_PROMPT", "none", 1); /* hint to UI */
execlp(askpass, askpass, prompt, (char *)NULL);
- error("%s: exec(%s): %s", __func__, askpass, strerror(errno));
+ error_f("exec(%s): %s", askpass, strerror(errno));
_exit(1);
/* NOTREACHED */
}
+ out_ctx:
if ((ret = calloc(1, sizeof(*ret))) == NULL) {
kill(pid, SIGTERM);
- fatal("%s: calloc failed", __func__);
+ fatal_f("calloc failed");
}
ret->pid = pid;
ret->osigchld = osigchld;
+ out:
free(prompt);
return ret;
}
void
-notify_complete(struct notifier_ctx *ctx)
+notify_complete(struct notifier_ctx *ctx, const char *fmt, ...)
{
int ret;
+ char *msg = NULL;
+ va_list args;
+
+ if (ctx != NULL && fmt != NULL && ctx->pid == -1) {
+ /*
+ * notify_start wrote to stderr, so send conclusion message
+ * there too
+ */
+ va_start(args, fmt);
+ xvasprintf(&msg, fmt, args);
+ va_end(args);
+ writemsg(msg);
+ free(msg);
+ }
if (ctx == NULL || ctx->pid <= 0) {
free(ctx);
@@ -288,7 +325,7 @@ notify_complete(struct notifier_ctx *ctx)
break;
}
if (ret == -1)
- fatal("%s: waitpid: %s", __func__, strerror(errno));
+ fatal_f("waitpid: %s", strerror(errno));
ssh_signal(SIGCHLD, ctx->osigchld);
free(ctx);
}
diff --git a/regress/Makefile b/regress/Makefile
index 62794d25f..0b5ad45d7 100644
--- a/regress/Makefile
+++ b/regress/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.108 2020/04/20 04:44:47 djm Exp $
+# $OpenBSD: Makefile,v 1.117 2021/09/03 04:11:13 dtucker Exp $
tests: prep file-tests t-exec unit
@@ -21,11 +21,13 @@ distclean: clean
LTESTS= connect \
proxy-connect \
+ sshfp-connect \
connect-privsep \
connect-uri \
proto-version \
proto-mismatch \
exit-status \
+ exit-status-signal \
envpass \
transfer \
banner \
@@ -41,12 +43,17 @@ LTESTS= connect \
agent-getpeereid \
agent-timeout \
agent-ptrace \
+ agent-subprocess \
keyscan \
keygen-change \
+ keygen-comment \
keygen-convert \
+ keygen-knownhosts \
keygen-moduli \
+ keygen-sshfp \
key-options \
scp \
+ scp3 \
scp-uri \
sftp \
sftp-chroot \
@@ -83,7 +90,6 @@ LTESTS= connect \
multipubkey \
limit-keytype \
hostkey-agent \
- keygen-knownhosts \
hostkey-rotate \
principals-command \
cert-file \
@@ -92,7 +98,7 @@ LTESTS= connect \
allow-deny-users \
authinfo \
sshsig \
- keygen-comment
+ knownhosts-command
INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers
@@ -113,7 +119,7 @@ CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \
host.ecdsa-sha2-nistp521 host.ssh-dss host.ssh-ed25519 \
host.ssh-rsa host_ca_key* host_krl_* host_revoked_* key.* \
key.dsa-* key.ecdsa-* key.ed25519-512 \
- key.ed25519-512.pub key.rsa-* keys-command-args kh.* \
+ key.ed25519-512.pub key.rsa-* keys-command-args kh.* askpass \
known_hosts known_hosts-cert known_hosts.* krl-* ls.copy \
modpipe netcat no_identity_config \
pidfile putty.rsa2 ready regress.log remote_pid \
@@ -121,9 +127,9 @@ CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \
rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \
scp-ssh-wrapper.scp setuid-allowed sftp-server.log \
sftp-server.sh sftp.log ssh-log-wrapper.sh ssh.log \
- ssh-rsa_oldfmt \
+ ssh-rsa_oldfmt knownhosts_command \
ssh_config ssh_config.* ssh_proxy ssh_proxy_bak \
- ssh_proxy_envpass sshd.log sshd_config sshd_config_minimal \
+ ssh_proxy_* sshd.log sshd_config sshd_config.* \
sshd_config.* sshd_proxy sshd_proxy.* sshd_proxy_bak \
sshd_proxy_orig t10.out t10.out.pub t12.out t12.out.pub \
t2.out t3.out t6.out1 t6.out2 t7.out t7.out.pub \
@@ -247,15 +253,20 @@ unit:
V="" ; \
test "x${USE_VALGRIND}" = "x" || \
V=${.CURDIR}/valgrind-unit.sh ; \
- $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \
- $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \
+ $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \
+ $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \
-d ${.CURDIR}/unittests/sshkey/testdata ; \
+ $$V ${.OBJDIR}/unittests/sshsig/test_sshsig \
+ -d ${.CURDIR}/unittests/sshsig/testdata ; \
+ $$V ${.OBJDIR}/unittests/authopt/test_authopt \
+ -d ${.CURDIR}/unittests/authopt/testdata ; \
$$V ${.OBJDIR}/unittests/bitmap/test_bitmap ; \
$$V ${.OBJDIR}/unittests/conversion/test_conversion ; \
$$V ${.OBJDIR}/unittests/kex/test_kex ; \
$$V ${.OBJDIR}/unittests/hostkeys/test_hostkeys \
-d ${.CURDIR}/unittests/hostkeys/testdata ; \
$$V ${.OBJDIR}/unittests/match/test_match ; \
+ $$V ${.OBJDIR}/unittests/misc/test_misc ; \
if test "x${TEST_SSH_UTF8}" = "xyes" ; then \
$$V ${.OBJDIR}/unittests/utf8/test_utf8 ; \
fi \
diff --git a/regress/addrmatch.sh b/regress/addrmatch.sh
index e7d29c3f3..26e0c9910 100644
--- a/regress/addrmatch.sh
+++ b/regress/addrmatch.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: addrmatch.sh,v 1.5 2020/03/13 03:18:45 djm Exp $
+# $OpenBSD: addrmatch.sh,v 1.6 2020/08/28 03:17:13 dtucker Exp $
# Placed in the Public Domain.
tid="address match"
@@ -52,5 +52,17 @@ run_trial user ::5 somehost ::1 1234 match3 "IP6 localaddress"
run_trial user ::5 somehost ::2 5678 match4 "IP6 localport"
fi
+#
+# Check that we catch invalid address/mask in Match Address/Localaddress
+#
+for i in 10.0.1.0/8 10.0.0.1/24 2000:aa:bb:01::/56; do
+ for a in address localaddress; do
+ verbose "test invalid Match $a $i"
+ echo "Match $a $i" > $OBJ/sshd_proxy
+ ${SUDO} ${SSHD} -f $OBJ/sshd_proxy -t >/dev/null 2>&1 && \
+ fail "accepted invalid match $a $i"
+ done
+done
+
cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
rm $OBJ/sshd_proxy_bak
diff --git a/regress/agent-getpeereid.sh b/regress/agent-getpeereid.sh
index 524340816..2874100fa 100644
--- a/regress/agent-getpeereid.sh
+++ b/regress/agent-getpeereid.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: agent-getpeereid.sh,v 1.11 2019/11/26 23:43:10 djm Exp $
+# $OpenBSD: agent-getpeereid.sh,v 1.13 2021/09/01 00:50:27 dtucker Exp $
# Placed in the Public Domain.
tid="disallow agent attach from other uid"
@@ -10,19 +10,15 @@ SSH_AUTH_SOCK=/nonexistent
if config_defined HAVE_GETPEEREID HAVE_GETPEERUCRED HAVE_SO_PEERCRED ; then
:
else
- echo "skipped (not supported on this platform)"
- exit 0
+ skip "skipped (not supported on this platform)"
fi
case "x$SUDO" in
xsudo) sudo=1;;
- xdoas) ;;
+ xdoas|xdoas\ *) ;;
x)
- echo "need SUDO to switch to uid $UNPRIV"
- echo SKIPPED
- exit 0 ;;
+ skip "need SUDO to switch to uid $UNPRIV" ;;
*)
- echo "unsupported $SUDO - "doas" and "sudo" are allowed"
- exit 0 ;;
+ skip "unsupported $SUDO - "doas" and "sudo" are allowed" ;;
esac
trace "start agent"
diff --git a/regress/agent-pkcs11.sh b/regress/agent-pkcs11.sh
index fbbaea518..268a70de8 100644
--- a/regress/agent-pkcs11.sh
+++ b/regress/agent-pkcs11.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: agent-pkcs11.sh,v 1.7 2019/11/26 23:43:10 djm Exp $
+# $OpenBSD: agent-pkcs11.sh,v 1.9 2021/07/25 12:13:03 dtucker Exp $
# Placed in the Public Domain.
tid="pkcs11 agent test"
@@ -62,16 +62,16 @@ notty() {
trace "generating keys"
RSA=${DIR}/RSA
EC=${DIR}/EC
-openssl genpkey -algorithm rsa > $RSA
-openssl pkcs8 -nocrypt -in $RSA |\
+$OPENSSL_BIN genpkey -algorithm rsa > $RSA
+$OPENSSL_BIN pkcs8 -nocrypt -in $RSA |\
softhsm2-util --slot "$slot" --label 01 --id 01 --pin "$TEST_SSH_PIN" --import /dev/stdin
-openssl genpkey \
+$OPENSSL_BIN genpkey \
-genparam \
-algorithm ec \
-pkeyopt ec_paramgen_curve:prime256v1 |\
- openssl genpkey \
+ $OPENSSL_BIN genpkey \
-paramfile /dev/stdin > $EC
-openssl pkcs8 -nocrypt -in $EC |\
+$OPENSSL_BIN pkcs8 -nocrypt -in $EC |\
softhsm2-util --slot "$slot" --label 02 --id 02 --pin "$TEST_SSH_PIN" --import /dev/stdin
trace "start agent"
diff --git a/regress/agent-subprocess.sh b/regress/agent-subprocess.sh
new file mode 100644
index 000000000..2f36d70cc
--- /dev/null
+++ b/regress/agent-subprocess.sh
@@ -0,0 +1,22 @@
+# $OpenBSD: agent-subprocess.sh,v 1.1 2020/06/19 05:07:09 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="agent subprocess"
+
+trace "ensure agent exits when run as subprocess"
+${SSHAGENT} sh -c "echo \$SSH_AGENT_PID >$OBJ/pidfile; sleep 1"
+
+pid=`cat $OBJ/pidfile`
+
+# Currently ssh-agent polls every 10s so we need to wait at least that long.
+n=12
+while kill -0 $pid >/dev/null 2>&1 && test "$n" -gt "0"; do
+ n=$(($n - 1))
+ sleep 1
+done
+
+if test "$n" -eq "0"; then
+ fail "agent still running"
+fi
+
+rm -f $OBJ/pidfile
diff --git a/regress/agent.sh b/regress/agent.sh
index 39403653c..f187b6757 100644
--- a/regress/agent.sh
+++ b/regress/agent.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: agent.sh,v 1.17 2019/12/21 02:33:07 djm Exp $
+# $OpenBSD: agent.sh,v 1.20 2021/02/25 03:27:34 djm Exp $
# Placed in the Public Domain.
tid="simple agent test"
@@ -45,17 +45,20 @@ for t in ${SSH_KEYTYPES}; do
# add to authorized keys
cat $OBJ/$t-agent.pub >> $OBJ/authorized_keys_$USER
# add private key to agent
- ${SSHADD} $OBJ/$t-agent #> /dev/null 2>&1
+ ${SSHADD} $OBJ/$t-agent > /dev/null 2>&1
if [ $? -ne 0 ]; then
fail "ssh-add failed exit code $?"
fi
# add private key to second agent
- SSH_AUTH_SOCK=$FW_SSH_AUTH_SOCK ${SSHADD} $OBJ/$t-agent #> /dev/null 2>&1
+ SSH_AUTH_SOCK=$FW_SSH_AUTH_SOCK ${SSHADD} $OBJ/$t-agent > /dev/null 2>&1
if [ $? -ne 0 ]; then
fail "ssh-add failed exit code $?"
fi
- # Remove private key to ensure that we aren't accidentally using it.
- rm -f $OBJ/$t-agent
+ # Move private key to ensure that we aren't accidentally using it.
+ # Keep the corresponding public keys/certs around for later use.
+ mv -f $OBJ/$t-agent $OBJ/$t-agent-private
+ cp -f $OBJ/$t-agent.pub $OBJ/$t-agent-private.pub
+ cp -f $OBJ/$t-agent-cert.pub $OBJ/$t-agent-private-cert.pub
done
# Remove explicit identity directives from ssh_proxy
@@ -84,8 +87,8 @@ fi
for t in ${SSH_KEYTYPES}; do
trace "connect via agent using $t key"
if [ "$t" = "ssh-dss" ]; then
- echo "PubkeyAcceptedKeyTypes +ssh-dss" >> $OBJ/ssh_proxy
- echo "PubkeyAcceptedKeyTypes +ssh-dss" >> $OBJ/sshd_proxy
+ echo "PubkeyAcceptedAlgorithms +ssh-dss" >> $OBJ/ssh_proxy
+ echo "PubkeyAcceptedAlgorithms +ssh-dss" >> $OBJ/sshd_proxy
fi
${SSH} -F $OBJ/ssh_proxy -i $OBJ/$t-agent.pub -oIdentitiesOnly=yes \
somehost exit 52
@@ -152,12 +155,72 @@ for t in ${SSH_KEYTYPES}; do
fi
done
+## Deletion tests.
+
trace "delete all agent keys"
${SSHADD} -D > /dev/null 2>&1
r=$?
if [ $r -ne 0 ]; then
fail "ssh-add -D failed: exit code $r"
fi
+# make sure they're gone
+${SSHADD} -l > /dev/null 2>&1
+r=$?
+if [ $r -ne 1 ]; then
+ fail "ssh-add -l returned unexpected exit code: $r"
+fi
+trace "readd keys"
+# re-add keys/certs to agent
+for t in ${SSH_KEYTYPES}; do
+ ${SSHADD} $OBJ/$t-agent-private >/dev/null 2>&1 || \
+ fail "ssh-add failed exit code $?"
+done
+# make sure they are there
+${SSHADD} -l > /dev/null 2>&1
+r=$?
+if [ $r -ne 0 ]; then
+ fail "ssh-add -l failed: exit code $r"
+fi
+
+check_key_absent() {
+ ${SSHADD} -L | grep "^$1 " >/dev/null
+ if [ $? -eq 0 ]; then
+ fail "$1 key unexpectedly present"
+ fi
+}
+check_key_present() {
+ ${SSHADD} -L | grep "^$1 " >/dev/null
+ if [ $? -ne 0 ]; then
+ fail "$1 key missing from agent"
+ fi
+}
+
+# delete the ed25519 key
+trace "delete single key by file"
+${SSHADD} -qdk $OBJ/ssh-ed25519-agent || fail "ssh-add -d ed25519 failed"
+check_key_absent ssh-ed25519
+check_key_present ssh-ed25519-cert-v01@openssh.com
+# Put key/cert back.
+${SSHADD} $OBJ/ssh-ed25519-agent-private >/dev/null 2>&1 || \
+ fail "ssh-add failed exit code $?"
+check_key_present ssh-ed25519
+# Delete both key and certificate.
+trace "delete key/cert by file"
+${SSHADD} -qd $OBJ/ssh-ed25519-agent || fail "ssh-add -d ed25519 failed"
+check_key_absent ssh-ed25519
+check_key_absent ssh-ed25519-cert-v01@openssh.com
+# Put key/cert back.
+${SSHADD} $OBJ/ssh-ed25519-agent-private >/dev/null 2>&1 || \
+ fail "ssh-add failed exit code $?"
+check_key_present ssh-ed25519
+# Delete certificate via stdin
+${SSHADD} -qd - < $OBJ/ssh-ed25519-agent-cert.pub || fail "ssh-add -d - failed"
+check_key_present ssh-ed25519
+check_key_absent ssh-ed25519-cert-v01@openssh.com
+# Delete key via stdin
+${SSHADD} -qd - < $OBJ/ssh-ed25519-agent.pub || fail "ssh-add -d - failed"
+check_key_absent ssh-ed25519
+check_key_absent ssh-ed25519-cert-v01@openssh.com
trace "kill agent"
${SSHAGENT} -k > /dev/null
diff --git a/regress/allow-deny-users.sh b/regress/allow-deny-users.sh
index 5c3895122..6c053eef0 100644
--- a/regress/allow-deny-users.sh
+++ b/regress/allow-deny-users.sh
@@ -1,6 +1,6 @@
# Public Domain
# Zev Weiss, 2016
-# $OpenBSD: allow-deny-users.sh,v 1.5 2018/07/13 02:13:50 djm Exp $
+# $OpenBSD: allow-deny-users.sh,v 1.6 2021/06/07 00:00:50 djm Exp $
tid="AllowUsers/DenyUsers"
@@ -20,10 +20,8 @@ test_auth()
failmsg="$4"
cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
- echo DenyUsers="$deny" >> $OBJ/sshd_proxy
- echo AllowUsers="$allow" >> $OBJ/sshd_proxy
-
- start_sshd -oDenyUsers="$deny" -oAllowUsers="$allow"
+ test -z "$deny" || echo DenyUsers="$deny" >> $OBJ/sshd_proxy
+ test -z "$allow" || echo AllowUsers="$allow" >> $OBJ/sshd_proxy
${SSH} -F $OBJ/ssh_proxy "$me@somehost" true
status=$?
diff --git a/regress/banner.sh b/regress/banner.sh
index 0d9654fe2..a84feb5ad 100644
--- a/regress/banner.sh
+++ b/regress/banner.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: banner.sh,v 1.3 2017/04/30 23:34:55 djm Exp $
+# $OpenBSD: banner.sh,v 1.4 2021/08/08 06:38:33 dtucker Exp $
# Placed in the Public Domain.
tid="banner"
@@ -37,7 +37,9 @@ done
trace "test suppress banner (-q)"
verbose "test $tid: suppress banner (-q)"
-( ${SSH} -q -F $OBJ/ssh_proxy otherhost true 2>$OBJ/banner.out && \
+# ssh-log-wrapper drops "-q" to preserve debug output so use ssh directly
+# for just this test.
+( ${REAL_SSH} -q -F $OBJ/ssh_proxy otherhost true 2>$OBJ/banner.out && \
cmp $OBJ/empty.in $OBJ/banner.out ) || \
fail "suppress banner (-q)"
diff --git a/regress/cert-hostkey.sh b/regress/cert-hostkey.sh
index 097bf8463..de8652b0e 100644
--- a/regress/cert-hostkey.sh
+++ b/regress/cert-hostkey.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: cert-hostkey.sh,v 1.23 2020/01/03 03:02:26 djm Exp $
+# $OpenBSD: cert-hostkey.sh,v 1.25 2021/06/08 22:30:27 djm Exp $
# Placed in the Public Domain.
tid="certified host keys"
@@ -29,12 +29,12 @@ for i in `$SSH -Q key | maybe_filter_sk`; do
done
(
echo "HostKeyAlgorithms ${types}"
- echo "PubkeyAcceptedKeyTypes *"
+ echo "PubkeyAcceptedAlgorithms *"
) >> $OBJ/ssh_proxy
cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
(
echo "HostKeyAlgorithms *"
- echo "PubkeyAcceptedKeyTypes *"
+ echo "PubkeyAcceptedAlgorithms *"
) >> $OBJ/sshd_proxy_bak
HOSTS='localhost-with-alias,127.0.0.1,::1'
@@ -283,11 +283,17 @@ for ktype in $PLAIN_TYPES ; do
) > $OBJ/sshd_proxy
${SSH} -oUserKnownHostsFile=$OBJ/known_hosts-cert \
- -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
- -F $OBJ/ssh_proxy somehost true
+ -oGlobalKnownHostsFile=none -F $OBJ/ssh_proxy somehost true
if [ $? -ne 0 ]; then
fail "ssh cert connect failed"
fi
+ # Also check that it works when the known_hosts file is not in the
+ # first array position.
+ ${SSH} -oUserKnownHostsFile="/dev/null $OBJ/known_hosts-cert" \
+ -oGlobalKnownHostsFile=none -F $OBJ/ssh_proxy somehost true
+ if [ $? -ne 0 ]; then
+ fail "ssh cert connect failed known_hosts 2nd"
+ fi
done
# Wrong certificate
diff --git a/regress/cert-userkey.sh b/regress/cert-userkey.sh
index 91596fa78..baa6903ea 100644
--- a/regress/cert-userkey.sh
+++ b/regress/cert-userkey.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: cert-userkey.sh,v 1.25 2020/01/03 03:02:26 djm Exp $
+# $OpenBSD: cert-userkey.sh,v 1.26 2021/02/25 03:27:34 djm Exp $
# Placed in the Public Domain.
tid="certified user keys"
@@ -71,11 +71,11 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do
echo "AuthorizedPrincipalsFile " \
"$OBJ/authorized_principals_%u"
echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
- echo "PubkeyAcceptedKeyTypes ${t}"
+ echo "PubkeyAcceptedAlgorithms ${t}"
) > $OBJ/sshd_proxy
(
cat $OBJ/ssh_proxy_bak
- echo "PubkeyAcceptedKeyTypes ${t}"
+ echo "PubkeyAcceptedAlgorithms ${t}"
) > $OBJ/ssh_proxy
# Missing authorized_principals
@@ -149,11 +149,11 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do
(
cat $OBJ/sshd_proxy_bak
echo "UsePrivilegeSeparation $privsep"
- echo "PubkeyAcceptedKeyTypes ${t}"
+ echo "PubkeyAcceptedAlgorithms ${t}"
) > $OBJ/sshd_proxy
(
cat $OBJ/ssh_proxy_bak
- echo "PubkeyAcceptedKeyTypes ${t}"
+ echo "PubkeyAcceptedAlgorithms ${t}"
) > $OBJ/ssh_proxy
# Wrong principals list
@@ -204,12 +204,12 @@ basic_tests() {
(
cat $OBJ/sshd_proxy_bak
echo "UsePrivilegeSeparation $privsep"
- echo "PubkeyAcceptedKeyTypes ${t}"
+ echo "PubkeyAcceptedAlgorithms ${t}"
echo "$extra_sshd"
) > $OBJ/sshd_proxy
(
cat $OBJ/ssh_proxy_bak
- echo "PubkeyAcceptedKeyTypes ${t}"
+ echo "PubkeyAcceptedAlgorithms ${t}"
) > $OBJ/ssh_proxy
${SSH} -i $OBJ/cert_user_key_${ktype} \
@@ -224,7 +224,7 @@ basic_tests() {
cat $OBJ/sshd_proxy_bak
echo "UsePrivilegeSeparation $privsep"
echo "RevokedKeys $OBJ/cert_user_key_revoked"
- echo "PubkeyAcceptedKeyTypes ${t}"
+ echo "PubkeyAcceptedAlgorithms ${t}"
echo "$extra_sshd"
) > $OBJ/sshd_proxy
cp $OBJ/cert_user_key_${ktype}.pub \
@@ -257,7 +257,7 @@ basic_tests() {
(
cat $OBJ/sshd_proxy_bak
echo "RevokedKeys $OBJ/user_ca_key.pub"
- echo "PubkeyAcceptedKeyTypes ${t}"
+ echo "PubkeyAcceptedAlgorithms ${t}"
echo "$extra_sshd"
) > $OBJ/sshd_proxy
${SSH} -i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \
@@ -270,7 +270,7 @@ basic_tests() {
verbose "$tid: $auth CA does not authenticate"
(
cat $OBJ/sshd_proxy_bak
- echo "PubkeyAcceptedKeyTypes ${t}"
+ echo "PubkeyAcceptedAlgorithms ${t}"
echo "$extra_sshd"
) > $OBJ/sshd_proxy
verbose "$tid: ensure CA key does not authenticate user"
@@ -308,7 +308,7 @@ test_one() {
echo > $OBJ/authorized_keys_$USER
echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" \
>> $OBJ/sshd_proxy
- echo "PubkeyAcceptedKeyTypes ${t}*" \
+ echo "PubkeyAcceptedAlgorithms ${t}*" \
>> $OBJ/sshd_proxy
if test "x$auth_opt" != "x" ; then
echo $auth_opt >> $OBJ/sshd_proxy
diff --git a/regress/cfginclude.sh b/regress/cfginclude.sh
index 2fc39ce45..f5b492f17 100644
--- a/regress/cfginclude.sh
+++ b/regress/cfginclude.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: cfginclude.sh,v 1.2 2016/05/03 15:30:46 dtucker Exp $
+# $OpenBSD: cfginclude.sh,v 1.3 2021/06/08 06:52:43 djm Exp $
# Placed in the Public Domain.
tid="config include"
@@ -10,7 +10,7 @@ cat > $OBJ/ssh_config.i << _EOF
Match host a
Hostname aa
-Match host b
+Match host b # comment
Hostname bb
Include $OBJ/ssh_config.i.*
@@ -19,10 +19,10 @@ Match host c
Hostname cc
Match host m
- Include $OBJ/ssh_config.i.*
+ Include $OBJ/ssh_config.i.* # comment
Host d
- Hostname dd
+ Hostname dd # comment
Host e
Hostname ee
@@ -47,17 +47,17 @@ Match host a
Match host b
Hostname bbb
-Match host c
+Match host c # comment
Hostname ccc
-Host d
+Host d # comment
Hostname ddd
Host e
Hostname eee
Host f
- Hostname fff
+ Hostname fff # comment
_EOF
cat > $OBJ/ssh_config.i.2 << _EOF
@@ -142,7 +142,7 @@ trial a aa
# cleanup
rm -f $OBJ/ssh_config.i $OBJ/ssh_config.i.* $OBJ/ssh_config.out
-# $OpenBSD: cfginclude.sh,v 1.2 2016/05/03 15:30:46 dtucker Exp $
+# $OpenBSD: cfginclude.sh,v 1.3 2021/06/08 06:52:43 djm Exp $
# Placed in the Public Domain.
tid="config include"
@@ -185,11 +185,11 @@ cat > $OBJ/ssh_config.i.1 << _EOF
Match host a
Hostname aaa
-Match host b
+Match host b # comment
Hostname bbb
Match host c
- Hostname ccc
+ Hostname ccc # comment
Host d
Hostname ddd
@@ -220,8 +220,8 @@ Host e
Host f
Hostname ffff
-Match all
- Hostname xxxx
+Match all # comment
+ Hostname xxxx # comment
_EOF
trial() {
diff --git a/regress/cfgmatch.sh b/regress/cfgmatch.sh
index 6620c84ed..05a666855 100644
--- a/regress/cfgmatch.sh
+++ b/regress/cfgmatch.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: cfgmatch.sh,v 1.12 2019/04/18 18:57:16 dtucker Exp $
+# $OpenBSD: cfgmatch.sh,v 1.13 2021/06/08 06:52:43 djm Exp $
# Placed in the Public Domain.
tid="sshd_config match"
@@ -39,16 +39,16 @@ stop_client()
}
cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
-echo "PermitOpen 127.0.0.1:1" >>$OBJ/sshd_config
+echo "PermitOpen 127.0.0.1:1 # comment" >>$OBJ/sshd_config
echo "Match Address 127.0.0.1" >>$OBJ/sshd_config
echo "PermitOpen 127.0.0.1:2 127.0.0.1:3 127.0.0.1:$PORT" >>$OBJ/sshd_config
grep -v AuthorizedKeysFile $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
-echo "AuthorizedKeysFile /dev/null" >>$OBJ/sshd_proxy
+echo "AuthorizedKeysFile /dev/null # comment" >>$OBJ/sshd_proxy
echo "PermitOpen 127.0.0.1:1" >>$OBJ/sshd_proxy
echo "Match user $USER" >>$OBJ/sshd_proxy
echo "AuthorizedKeysFile /dev/null $OBJ/authorized_keys_%u" >>$OBJ/sshd_proxy
-echo "Match Address 127.0.0.1" >>$OBJ/sshd_proxy
+echo "Match Address 127.0.0.1 # comment" >>$OBJ/sshd_proxy
echo "PermitOpen 127.0.0.1:2 127.0.0.1:3 127.0.0.1:$PORT" >>$OBJ/sshd_proxy
${SUDO} ${SSHD} -f $OBJ/sshd_config -T >/dev/null || \
diff --git a/regress/connect-privsep.sh b/regress/connect-privsep.sh
index b6abb65e3..8970340a2 100644
--- a/regress/connect-privsep.sh
+++ b/regress/connect-privsep.sh
@@ -16,13 +16,12 @@ echo 'UsePrivilegeSeparation sandbox' >> $OBJ/sshd_proxy
${SSH} -F $OBJ/ssh_proxy 999.999.999.999 true
if [ $? -ne 0 ]; then
- # XXX replace this with fail once sandbox has stabilised
- warn "ssh privsep/sandbox+proxyconnect failed"
+ fail "ssh privsep/sandbox+proxyconnect failed"
fi
# Because sandbox is sensitive to changes in libc, especially malloc, retest
# with every malloc.conf option (and none).
-if [ -z "TEST_MALLOC_OPTIONS" ]; then
+if [ -z "$TEST_MALLOC_OPTIONS" ]; then
mopts="C F G J R S U X < >"
else
mopts=`echo $TEST_MALLOC_OPTIONS | sed 's/./& /g'`
diff --git a/regress/dhgex.sh b/regress/dhgex.sh
index ae64a9fb6..6dd4cfe3f 100644
--- a/regress/dhgex.sh
+++ b/regress/dhgex.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: dhgex.sh,v 1.6 2019/10/06 11:49:50 dtucker Exp $
+# $OpenBSD: dhgex.sh,v 1.7 2020/12/21 22:48:41 dtucker Exp $
# Placed in the Public Domain.
tid="dhgex"
@@ -58,4 +58,4 @@ check 3072 3des-cbc # 112 bits.
check 3072 `${SSH} -Q cipher | grep 128`
check 7680 `${SSH} -Q cipher | grep 192`
check 8192 `${SSH} -Q cipher | grep 256`
-check 8192 rijndael-cbc@lysator.liu.se chacha20-poly1305@openssh.com
+check 8192 chacha20-poly1305@openssh.com
diff --git a/regress/ed25519_openssh.prv b/regress/ed25519_openssh.prv
new file mode 100644
index 000000000..9f191b778
--- /dev/null
+++ b/regress/ed25519_openssh.prv
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACDE8/0FM7Yw6xc53QpiZUQAh/LK2mEAwNDNYdSR6GIGIwAAAKC+Cfdzvgn3
+cwAAAAtzc2gtZWQyNTUxOQAAACDE8/0FM7Yw6xc53QpiZUQAh/LK2mEAwNDNYdSR6GIGIw
+AAAEBm+60DgH0WMW7Z5oyvu1dxo7MaXe5RRMWTMJCfLkHexMTz/QUztjDrFzndCmJlRACH
+8sraYQDA0M1h1JHoYgYjAAAAGWR0dWNrZXJAcXVvbGwuZHR1Y2tlci5uZXQBAgME
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/ed25519_openssh.pub b/regress/ed25519_openssh.pub
new file mode 100644
index 000000000..910363138
--- /dev/null
+++ b/regress/ed25519_openssh.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMTz/QUztjDrFzndCmJlRACH8sraYQDA0M1h1JHoYgYj
diff --git a/regress/exit-status-signal.sh b/regress/exit-status-signal.sh
new file mode 100644
index 000000000..1b3af0d84
--- /dev/null
+++ b/regress/exit-status-signal.sh
@@ -0,0 +1,24 @@
+# This test performs validation that ssh client is not successive on being terminated
+
+tid="exit status on signal"
+
+# spawn client in background
+rm -f $OBJ/remote_pid
+${SSH} -F $OBJ/ssh_proxy somehost 'echo $$ >'$OBJ'/remote_pid; sleep 444' &
+ssh_pid=$!
+
+# wait for it to start
+n=20
+while [ ! -f $OBJ/remote_pid ] && [ $n -gt 0 ]; do
+ n=$(($n - 1))
+ sleep 1
+done
+
+kill $ssh_pid
+wait $ssh_pid
+exit_code=$?
+
+if [ $exit_code -eq 0 ]; then
+ fail "ssh client should fail on signal"
+fi
+
diff --git a/regress/forward-control.sh b/regress/forward-control.sh
index 3b1f69a71..02f7667a6 100644
--- a/regress/forward-control.sh
+++ b/regress/forward-control.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: forward-control.sh,v 1.7 2018/06/07 14:29:43 djm Exp $
+# $OpenBSD: forward-control.sh,v 1.8 2021/05/07 09:23:40 dtucker Exp $
# Placed in the Public Domain.
tid="sshd control of local and remote forwarding"
@@ -46,7 +46,7 @@ check_lfwd() {
wait_for_file_to_appear $READY || \
fatal "check_lfwd ssh fail: $_message"
${SSH} -F $OBJ/ssh_config -p $LFWD_PORT \
- -oConnectionAttempts=4 host true >/dev/null 2>&1
+ -oConnectionAttempts=10 host true >/dev/null 2>&1
_result=$?
kill $_sshpid `cat $READY` 2>/dev/null
wait_for_process_to_exit $_sshpid
@@ -76,7 +76,7 @@ check_rfwd() {
_result=$?
if test $_result -eq 0 ; then
${SSH} -F $OBJ/ssh_config -p $RFWD_PORT \
- -oConnectionAttempts=4 host true >/dev/null 2>&1
+ -oConnectionAttempts=10 host true >/dev/null 2>&1
_result=$?
kill $_sshpid `cat $READY` 2>/dev/null
wait_for_process_to_exit $_sshpid
diff --git a/regress/forwarding.sh b/regress/forwarding.sh
index cd634f2f6..a72bd3a05 100644
--- a/regress/forwarding.sh
+++ b/regress/forwarding.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: forwarding.sh,v 1.23 2019/07/20 09:50:58 dtucker Exp $
+# $OpenBSD: forwarding.sh,v 1.24 2021/05/07 09:23:40 dtucker Exp $
# Placed in the Public Domain.
tid="local and remote forwarding"
@@ -29,7 +29,7 @@ rm -f $CTL
${SSH} -S $CTL -N -M -F $OBJ/ssh_config -f $fwd somehost
trace "transfer over forwarded channels and check result"
-${SSH} -F $OBJ/ssh_config -p$last -o 'ConnectionAttempts=4' \
+${SSH} -F $OBJ/ssh_config -p$last -o 'ConnectionAttempts=10' \
somehost cat ${DATA} > ${COPY}
test -s ${COPY} || fail "failed copy of ${DATA}"
cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}"
@@ -110,7 +110,7 @@ rm -f $CTL
${SSH} -S $CTL -N -M -F $OBJ/ssh_config -f somehost
trace "config file: transfer over forwarded channels and check result"
-${SSH} -F $OBJ/ssh_config -p${base}02 -o 'ConnectionAttempts=4' \
+${SSH} -F $OBJ/ssh_config -p${base}02 -o 'ConnectionAttempts=10' \
somehost cat ${DATA} > ${COPY}
test -s ${COPY} || fail "failed copy of ${DATA}"
cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}"
@@ -124,7 +124,7 @@ ${SSH} -S $CTL -N -M -f -F $OBJ/ssh_config -R${base}01:[$OBJ/unix-1.fwd] somehos
${SSH} -S $CTL.1 -N -M -f -F $OBJ/ssh_config -L[$OBJ/unix-1.fwd]:[$OBJ/unix-2.fwd] somehost
${SSH} -S $CTL.2 -N -M -f -F $OBJ/ssh_config -R[$OBJ/unix-2.fwd]:[$OBJ/unix-3.fwd] somehost
${SSH} -S $CTL.3 -N -M -f -F $OBJ/ssh_config -L[$OBJ/unix-3.fwd]:127.0.0.1:$PORT somehost
-${SSH} -F $OBJ/ssh_config -p${base}01 -o 'ConnectionAttempts=4' \
+${SSH} -F $OBJ/ssh_config -p${base}01 -o 'ConnectionAttempts=10' \
somehost cat ${DATA} > ${COPY}
test -s ${COPY} || fail "failed copy ${DATA}"
cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}"
diff --git a/regress/hostkey-rotate.sh b/regress/hostkey-rotate.sh
index c3e100c3e..0ae0c3dfc 100644
--- a/regress/hostkey-rotate.sh
+++ b/regress/hostkey-rotate.sh
@@ -1,12 +1,34 @@
-# $OpenBSD: hostkey-rotate.sh,v 1.8 2019/11/26 23:43:10 djm Exp $
+# $OpenBSD: hostkey-rotate.sh,v 1.9 2020/10/07 06:38:16 djm Exp $
# Placed in the Public Domain.
tid="hostkey rotate"
-rm -f $OBJ/hkr.* $OBJ/ssh_proxy.orig
+#
+# GNU (f)grep <=2.18, as shipped by FreeBSD<=12 and NetBSD<=9 will occasionally
+# fail to find ssh host keys in the hostkey-rotate test. If we have those
+# versions, use awk instead.
+# See # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=258616
+#
+case `grep --version 2>&1 | awk '/GNU grep/{print $4}'` in
+2.19) fgrep=good ;;
+1.*|2.?|2.?.?|2.1?) fgrep=bad ;; # stock GNU grep
+2.5.1*) fgrep=bad ;; # FreeBSD and NetBSD
+*) fgrep=good ;;
+esac
+if test "x$fgrep" = "xbad"; then
+ fgrep()
+{
+ awk 'BEGIN{e=1} {if (index($0,"'$1'")>0){e=0;print}} END{exit e}' $2
+}
+fi
+
+rm -f $OBJ/hkr.* $OBJ/ssh_proxy.orig $OBJ/ssh_proxy.orig
grep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig
+mv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig
+grep -vi 'globalknownhostsfile' $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy
echo "UpdateHostkeys=yes" >> $OBJ/ssh_proxy
+echo "GlobalKnownHostsFile=none" >> $OBJ/ssh_proxy
rm $OBJ/known_hosts
# The "primary" key type is ed25519 since it's supported even when built
diff --git a/regress/key-options.sh b/regress/key-options.sh
index 097f46eba..2f3d66e2e 100644
--- a/regress/key-options.sh
+++ b/regress/key-options.sh
@@ -9,7 +9,7 @@ cp $authkeys $origkeys
# Allocating ptys can require privileges on some platforms.
skip_pty=""
-if ! config_defined HAVE_OPENPTY && [ "x$SUDO" == "x" ]; then
+if ! config_defined HAVE_OPENPTY && [ "x$SUDO" = "x" ]; then
skip_pty="no openpty(3) and SUDO not set"
fi
diff --git a/regress/keygen-convert.sh b/regress/keygen-convert.sh
index fce110ea1..95656581c 100644
--- a/regress/keygen-convert.sh
+++ b/regress/keygen-convert.sh
@@ -1,40 +1,54 @@
-# $OpenBSD: keygen-convert.sh,v 1.2 2019/07/23 07:55:29 dtucker Exp $
+# $OpenBSD: keygen-convert.sh,v 1.6 2021/07/24 02:57:28 dtucker Exp $
# Placed in the Public Domain.
tid="convert keys"
-types=""
-for i in ${SSH_KEYTYPES}; do
- case "$i" in
- ssh-dss) types="$types dsa" ;;
- ssh-rsa) types="$types rsa" ;;
- esac
-done
+cat > $OBJ/askpass <<EOD
+#!/bin/sh
+echo hunter2
+EOD
+chmod u+x $OBJ/askpass
+
+if ${SSHKEYGEN} -? 2>&1 | grep "ssh-keygen -e" >/dev/null; then
+ test_import_export=1
+fi
-for t in $types; do
+for t in ${SSH_KEYTYPES}; do
# generate user key for agent
trace "generating $t key"
rm -f $OBJ/$t-key
${SSHKEYGEN} -q -N "" -t $t -f $OBJ/$t-key
- trace "export $t private to rfc4716 public"
- ${SSHKEYGEN} -q -e -f $OBJ/$t-key >$OBJ/$t-key-rfc || \
- fail "export $t private to rfc4716 public"
+ if test "x$test_import_export" = "x1"; then
+ trace "export $t private to rfc4716 public"
+ ${SSHKEYGEN} -q -e -f $OBJ/$t-key >$OBJ/$t-key-rfc || \
+ fail "export $t private to rfc4716 public"
+
+ trace "export $t public to rfc4716 public"
+ ${SSHKEYGEN} -q -e -f $OBJ/$t-key.pub >$OBJ/$t-key-rfc.pub || \
+ fail "$t public to rfc4716 public"
+
+ cmp $OBJ/$t-key-rfc $OBJ/$t-key-rfc.pub || \
+ fail "$t rfc4716 exports differ between public and private"
- trace "export $t public to rfc4716 public"
- ${SSHKEYGEN} -q -e -f $OBJ/$t-key.pub >$OBJ/$t-key-rfc.pub || \
- fail "$t public to rfc4716 public"
+ trace "import $t rfc4716 public"
+ ${SSHKEYGEN} -q -i -f $OBJ/$t-key-rfc >$OBJ/$t-rfc-imported || \
+ fail "$t import rfc4716 public"
- cmp $OBJ/$t-key-rfc $OBJ/$t-key-rfc.pub || \
- fail "$t rfc4716 exports differ between public and private"
+ cut -f1,2 -d " " $OBJ/$t-key.pub >$OBJ/$t-key-nocomment.pub
+ cmp $OBJ/$t-key-nocomment.pub $OBJ/$t-rfc-imported || \
+ fail "$t imported differs from original"
+ fi
- trace "import $t rfc4716 public"
- ${SSHKEYGEN} -q -i -f $OBJ/$t-key-rfc >$OBJ/$t-rfc-imported || \
- fail "$t import rfc4716 public"
+ trace "set passphrase $t"
+ ${SSHKEYGEN} -q -p -P '' -N 'hunter2' -f $OBJ/$t-key >/dev/null || \
+ fail "$t set passphrase failed"
- cut -f1,2 -d " " $OBJ/$t-key.pub >$OBJ/$t-key-nocomment.pub
- cmp $OBJ/$t-key-nocomment.pub $OBJ/$t-rfc-imported || \
- fail "$t imported differs from original"
+ trace "export $t to public with passphrase"
+ SSH_ASKPASS=$OBJ/askpass SSH_ASKPASS_REQUIRE=force \
+ ${SSHKEYGEN} -y -f $OBJ/$t-key >$OBJ/$t-key-nocomment.pub
+ cmp $OBJ/$t-key.pub $OBJ/$t-key-nocomment.pub || \
+ fail "$t exported pubkey differs from generated"
rm -f $OBJ/$t-key $OBJ/$t-key.pub $OBJ/$t-key-rfc $OBJ/$t-key-rfc.pub \
$OBJ/$t-rfc-imported $OBJ/$t-key-nocomment.pub
diff --git a/regress/keygen-sshfp.sh b/regress/keygen-sshfp.sh
new file mode 100644
index 000000000..2abf9adec
--- /dev/null
+++ b/regress/keygen-sshfp.sh
@@ -0,0 +1,29 @@
+# $OpenBSD: keygen-sshfp.sh,v 1.2 2021/07/19 02:29:28 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="keygen-sshfp"
+
+trace "keygen fingerprints"
+fp=`${SSHKEYGEN} -r test -f ${SRC}/ed25519_openssh.pub | \
+ awk '$5=="1"{print $6}'`
+if [ "$fp" != "8a8647a7567e202ce317e62606c799c53d4c121f" ]; then
+ fail "keygen fingerprint sha1"
+fi
+fp=`${SSHKEYGEN} -r test -f ${SRC}/ed25519_openssh.pub | \
+ awk '$5=="2"{print $6}'`
+if [ "$fp" != \
+ "54a506fb849aafb9f229cf78a94436c281efcb4ae67c8a430e8c06afcb5ee18f" ]; then
+ fail "keygen fingerprint sha256"
+fi
+
+if ${SSH} -Q key-plain | grep ssh-rsa >/dev/null; then
+ fp=`${SSHKEYGEN} -r test -f ${SRC}/rsa_openssh.pub | awk '$5=="1"{print $6}'`
+ if [ "$fp" != "99c79cc09f5f81069cc017cdf9552cfc94b3b929" ]; then
+ fail "keygen fingerprint sha1"
+ fi
+ fp=`${SSHKEYGEN} -r test -f ${SRC}/rsa_openssh.pub | awk '$5=="2"{print $6}'`
+ if [ "$fp" != \
+ "e30d6b9eb7a4de495324e4d5870b8220577993ea6af417e8e4a4f1c5bf01a9b6" ]; then
+ fail "keygen fingerprint sha256"
+ fi
+fi
diff --git a/regress/keys-command.sh b/regress/keys-command.sh
index 33b6e7b42..a3acf5e4d 100644
--- a/regress/keys-command.sh
+++ b/regress/keys-command.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: keys-command.sh,v 1.6 2019/07/25 08:48:11 dtucker Exp $
+# $OpenBSD: keys-command.sh,v 1.7 2021/09/01 00:50:27 dtucker Exp $
# Placed in the Public Domain.
tid="authorized keys from command"
@@ -77,5 +77,5 @@ if [ -x $KEY_COMMAND ]; then
fail "connect failed"
fi
else
- echo "SKIPPED: $KEY_COMMAND not executable (/var/run mounted noexec?)"
+ skip "$KEY_COMMAND not executable (/var/run mounted noexec?)"
fi
diff --git a/regress/keytype.sh b/regress/keytype.sh
index 20a8ceaf2..f1c045183 100644
--- a/regress/keytype.sh
+++ b/regress/keytype.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: keytype.sh,v 1.10 2019/12/16 02:39:05 djm Exp $
+# $OpenBSD: keytype.sh,v 1.11 2021/02/25 03:27:34 djm Exp $
# Placed in the Public Domain.
tid="login with different key types"
@@ -58,13 +58,13 @@ for ut in $ktypes; do
(
grep -v HostKey $OBJ/sshd_proxy_bak
echo HostKey $OBJ/key.$ht
- echo PubkeyAcceptedKeyTypes $user_type
+ echo PubkeyAcceptedAlgorithms $user_type
echo HostKeyAlgorithms $host_type
) > $OBJ/sshd_proxy
(
grep -v IdentityFile $OBJ/ssh_proxy_bak
echo IdentityFile $OBJ/key.$ut
- echo PubkeyAcceptedKeyTypes $user_type
+ echo PubkeyAcceptedAlgorithms $user_type
echo HostKeyAlgorithms $host_type
) > $OBJ/ssh_proxy
(
diff --git a/regress/knownhosts-command.sh b/regress/knownhosts-command.sh
new file mode 100644
index 000000000..8472ec812
--- /dev/null
+++ b/regress/knownhosts-command.sh
@@ -0,0 +1,55 @@
+# $OpenBSD: knownhosts-command.sh,v 1.3 2021/08/30 01:15:45 djm Exp $
+# Placed in the Public Domain.
+
+tid="known hosts command "
+
+rm -f $OBJ/knownhosts_command $OBJ/ssh_proxy_khc
+cp $OBJ/ssh_proxy $OBJ/ssh_proxy_orig
+
+( grep -vi GlobalKnownHostsFile $OBJ/ssh_proxy_orig | \
+ grep -vi UserKnownHostsFile;
+ echo "GlobalKnownHostsFile none" ;
+ echo "UserKnownHostsFile none" ;
+ echo "KnownHostsCommand $OBJ/knownhosts_command '%t' '%K' '%u'" ;
+) > $OBJ/ssh_proxy
+
+verbose "simple connection"
+cat > $OBJ/knownhosts_command << _EOF
+#!/bin/sh
+cat $OBJ/known_hosts
+_EOF
+chmod a+x $OBJ/knownhosts_command
+${SSH} -F $OBJ/ssh_proxy x true || fail "ssh connect failed"
+
+verbose "no keys"
+cat > $OBJ/knownhosts_command << _EOF
+#!/bin/sh
+exit 0
+_EOF
+chmod a+x $OBJ/knownhosts_command
+${SSH} -F $OBJ/ssh_proxy x true && fail "ssh connect succeeded with no keys"
+
+verbose "bad exit status"
+cat > $OBJ/knownhosts_command << _EOF
+#!/bin/sh
+cat $OBJ/known_hosts
+exit 1
+_EOF
+chmod a+x $OBJ/knownhosts_command
+${SSH} -F $OBJ/ssh_proxy x true && fail "ssh connect succeeded with bad exit"
+
+for keytype in ${SSH_HOSTKEY_TYPES} ; do
+ 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
+#!/bin/sh
+die() { echo "\$@" 1>&2 ; exit 1; }
+test "x\$1" = "x$keytype" || die "wrong keytype \$1 (expected $keytype)"
+test "x\$3" = "x$LOGNAME" || die "wrong username \$3 (expected $LOGNAME)"
+grep -- "\$1.*\$2" $OBJ/known_hosts
+_EOF
+ ${SSH} -F $OBJ/ssh_proxy -oHostKeyAlgorithms=$algs x true ||
+ fail "ssh connect failed for keytype $x"
+done
diff --git a/regress/limit-keytype.sh b/regress/limit-keytype.sh
index 010a88cd7..7127de007 100644
--- a/regress/limit-keytype.sh
+++ b/regress/limit-keytype.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: limit-keytype.sh,v 1.9 2019/12/16 02:39:05 djm Exp $
+# $OpenBSD: limit-keytype.sh,v 1.10 2021/02/25 03:27:34 djm Exp $
# Placed in the Public Domain.
tid="restrict pubkey type"
@@ -69,7 +69,7 @@ prepare_config() {
) > $OBJ/sshd_proxy
}
-# Return the required parameter for PubkeyAcceptedKeyTypes corresponding to
+# Return the required parameter for PubkeyAcceptedAlgorithms corresponding to
# the supplied key type.
keytype() {
case "$1" in
@@ -92,14 +92,14 @@ ${SSH} $opts -i $OBJ/user_key2 proxy true || fatal "key2 failed"
# Allow plain Ed25519 and RSA. The certificate should fail.
verbose "allow $ktype2,$ktype1"
prepare_config \
- "PubkeyAcceptedKeyTypes `keytype $ktype2`,`keytype $ktype1`"
+ "PubkeyAcceptedAlgorithms `keytype $ktype2`,`keytype $ktype1`"
${SSH} $certopts proxy true && fatal "cert succeeded"
${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed"
${SSH} $opts -i $OBJ/user_key2 proxy true || fatal "key2 failed"
# Allow Ed25519 only.
verbose "allow $ktype1"
-prepare_config "PubkeyAcceptedKeyTypes `keytype $ktype1`"
+prepare_config "PubkeyAcceptedAlgorithms `keytype $ktype1`"
${SSH} $certopts proxy true && fatal "cert succeeded"
${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed"
if [ "$ktype1" != "$ktype2" ]; then
@@ -108,15 +108,15 @@ fi
# Allow all certs. Plain keys should fail.
verbose "allow cert only"
-prepare_config "PubkeyAcceptedKeyTypes *-cert-v01@openssh.com"
+prepare_config "PubkeyAcceptedAlgorithms *-cert-v01@openssh.com"
${SSH} $certopts proxy true || fatal "cert failed"
${SSH} $opts -i $OBJ/user_key1 proxy true && fatal "key1 succeeded"
${SSH} $opts -i $OBJ/user_key2 proxy true && fatal "key2 succeeded"
# Allow RSA in main config, Ed25519 for non-existent user.
verbose "match w/ no match"
-prepare_config "PubkeyAcceptedKeyTypes `keytype $ktype2`" \
- "Match user x$USER" "PubkeyAcceptedKeyTypes +`keytype $ktype1`"
+prepare_config "PubkeyAcceptedAlgorithms `keytype $ktype2`" \
+ "Match user x$USER" "PubkeyAcceptedAlgorithms +`keytype $ktype1`"
${SSH} $certopts proxy true && fatal "cert succeeded"
if [ "$ktype1" != "$ktype2" ]; then
${SSH} $opts -i $OBJ/user_key1 proxy true && fatal "key1 succeeded"
@@ -125,8 +125,8 @@ ${SSH} $opts -i $OBJ/user_key2 proxy true || fatal "key2 failed"
# Allow only DSA in main config, Ed25519 for user.
verbose "match w/ matching"
-prepare_config "PubkeyAcceptedKeyTypes `keytype $ktype4`" \
- "Match user $USER" "PubkeyAcceptedKeyTypes +`keytype $ktype1`"
+prepare_config "PubkeyAcceptedAlgorithms `keytype $ktype4`" \
+ "Match user $USER" "PubkeyAcceptedAlgorithms +`keytype $ktype1`"
${SSH} $certopts proxy true || fatal "cert failed"
${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed"
${SSH} $opts -i $OBJ/user_key4 proxy true && fatal "key4 succeeded"
diff --git a/regress/misc/Makefile b/regress/misc/Makefile
index cf95f265c..b9149f287 100644
--- a/regress/misc/Makefile
+++ b/regress/misc/Makefile
@@ -1,3 +1,3 @@
-SUBDIR= kexfuzz sk-dummy
+SUBDIR= sk-dummy
.include <bsd.subdir.mk>
diff --git a/regress/misc/fuzz-harness/Makefile b/regress/misc/fuzz-harness/Makefile
index 64fbdbab1..e879fcdae 100644
--- a/regress/misc/fuzz-harness/Makefile
+++ b/regress/misc/fuzz-harness/Makefile
@@ -1,38 +1,52 @@
# NB. libssh and libopenbsd-compat should be built with the same sanitizer opts.
-CXX=clang++-6.0
-FUZZ_FLAGS=-fsanitize=address,undefined -fsanitize-coverage=edge,trace-pc
+CC=clang-11
+CXX=clang++-11
+FUZZ_FLAGS=-fsanitize=address,fuzzer -fno-omit-frame-pointer
FUZZ_LIBS=-lFuzzer
CXXFLAGS=-O2 -g -Wall -Wextra -Wno-unused-parameter -I ../../.. $(FUZZ_FLAGS)
+CFLAGS=$(CXXFLAGS)
LDFLAGS=-L ../../.. -L ../../../openbsd-compat -g $(FUZZ_FLAGS)
LIBS=-lssh -lopenbsd-compat -lcrypto -lfido2 -lcbor $(FUZZ_LIBS)
-COMMON_OBJS=ssh-sk-null.o
+SK_NULL_OBJS=ssh-sk-null.o
+COMMON_DEPS=../../../libssh.a
TARGETS=pubkey_fuzz sig_fuzz authopt_fuzz sshsig_fuzz \
- sshsigopt_fuzz privkey_fuzz
+ sshsigopt_fuzz privkey_fuzz kex_fuzz agent_fuzz
all: $(TARGETS)
.cc.o:
$(CXX) $(CXXFLAGS) -c $< -o $@
-pubkey_fuzz: pubkey_fuzz.o $(COMMON_OBJS)
- $(CXX) -o $@ pubkey_fuzz.o $(COMMON_OBJS) $(LDFLAGS) $(LIBS)
+pubkey_fuzz: pubkey_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS)
+ $(CXX) -o $@ pubkey_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(LIBS)
-sig_fuzz: sig_fuzz.o $(COMMON_OBJS)
- $(CXX) -o $@ sig_fuzz.o $(COMMON_OBJS) $(LDFLAGS) $(LIBS)
+sig_fuzz: sig_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS)
+ $(CXX) -o $@ sig_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(LIBS)
-authopt_fuzz: authopt_fuzz.o $(COMMON_OBJS)
- $(CXX) -o $@ authopt_fuzz.o $(COMMON_OBJS) ../../../auth-options.o $(LDFLAGS) $(LIBS)
+authopt_fuzz: authopt_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS)
+ $(CXX) -o $@ authopt_fuzz.o $(SK_NULL_OBJS) ../../../auth-options.o $(LDFLAGS) $(LIBS)
-sshsig_fuzz: sshsig_fuzz.o $(COMMON_OBJS)
- $(CXX) -o $@ sshsig_fuzz.o $(COMMON_OBJS) ../../../sshsig.o $(LDFLAGS) $(LIBS)
+sshsig_fuzz: sshsig_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS)
+ $(CXX) -o $@ sshsig_fuzz.o $(SK_NULL_OBJS) ../../../sshsig.o $(LDFLAGS) $(LIBS)
-sshsigopt_fuzz: sshsigopt_fuzz.o $(COMMON_OBJS)
- $(CXX) -o $@ sshsigopt_fuzz.o $(COMMON_OBJS) ../../../sshsig.o $(LDFLAGS) $(LIBS)
+sshsigopt_fuzz: sshsigopt_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS)
+ $(CXX) -o $@ sshsigopt_fuzz.o $(SK_NULL_OBJS) ../../../sshsig.o $(LDFLAGS) $(LIBS)
-privkey_fuzz: privkey_fuzz.o $(COMMON_OBJS)
- $(CXX) -o $@ privkey_fuzz.o $(COMMON_OBJS) $(LDFLAGS) $(LIBS)
+privkey_fuzz: privkey_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS)
+ $(CXX) -o $@ privkey_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(LIBS)
+
+kex_fuzz: kex_fuzz.o $(SK_NULL_OBJS) $(COMMON_DEPS)
+ $(CXX) -o $@ kex_fuzz.o $(SK_NULL_OBJS) $(LDFLAGS) $(LIBS) -lz
+
+agent_fuzz: agent_fuzz.o agent_fuzz_helper.o sk-dummy.o ../../../ssh-sk.o $(COMMON_DEPS)
+ $(CXX) -o $@ agent_fuzz.o agent_fuzz_helper.o sk-dummy.o ../../../ssh-sk.o $(LDFLAGS) $(LIBS) -lz
+
+agent_fuzz_helper.o: agent_fuzz_helper.c ../../../ssh-agent.c
+
+sk-dummy.o: ../sk-dummy/sk-dummy.c
+ $(CC) $(CFLAGS) -c -o $@ ../sk-dummy/sk-dummy.c -DSK_DUMMY_INTEGRATE=1 $(LDFLAGS)
clean:
-rm -f *.o $(TARGETS)
diff --git a/regress/misc/fuzz-harness/agent_fuzz.cc b/regress/misc/fuzz-harness/agent_fuzz.cc
new file mode 100644
index 000000000..ad85b2f9a
--- /dev/null
+++ b/regress/misc/fuzz-harness/agent_fuzz.cc
@@ -0,0 +1,15 @@
+// cc_fuzz_target test for ssh-agent.
+extern "C" {
+
+#include <stdint.h>
+#include <sys/types.h>
+
+extern void test_one(const uint8_t* s, size_t slen);
+
+int LLVMFuzzerTestOneInput(const uint8_t* s, size_t slen)
+{
+ test_one(s, slen);
+ return 0;
+}
+
+} // extern
diff --git a/regress/misc/fuzz-harness/agent_fuzz_helper.c b/regress/misc/fuzz-harness/agent_fuzz_helper.c
new file mode 100644
index 000000000..1d419820c
--- /dev/null
+++ b/regress/misc/fuzz-harness/agent_fuzz_helper.c
@@ -0,0 +1,177 @@
+#include "fixed-keys.h"
+#include <assert.h>
+
+#define main(ac, av) xxxmain(ac, av)
+#include "../../../ssh-agent.c"
+
+void test_one(const uint8_t* s, size_t slen);
+
+static int
+devnull_or_die(void)
+{
+ int fd;
+
+ if ((fd = open("/dev/null", O_RDWR)) == -1) {
+ error_f("open /dev/null: %s", strerror(errno));
+ abort();
+ }
+ return fd;
+}
+
+static struct sshkey *
+pubkey_or_die(const char *s)
+{
+ char *tmp, *cp;
+ struct sshkey *pubkey;
+ int r;
+
+ tmp = cp = xstrdup(s);
+ if ((pubkey = sshkey_new(KEY_UNSPEC)) == NULL)
+ abort();
+ if ((r = sshkey_read(pubkey, &cp)) != 0) {
+ error_fr(r, "parse");
+ abort();
+ }
+ free(tmp);
+ return pubkey;
+}
+
+static struct sshkey *
+privkey_or_die(const char *s)
+{
+ int r;
+ struct sshbuf *b;
+ struct sshkey *privkey;
+
+ if ((b = sshbuf_from(s, strlen(s))) == NULL) {
+ error_f("sshbuf_from failed");
+ abort();
+ }
+ if ((r = sshkey_parse_private_fileblob(b, "", &privkey, NULL)) != 0) {
+ error_fr(r, "parse");
+ abort();
+ }
+ sshbuf_free(b);
+ return privkey;
+}
+
+static void
+add_key(const char *privkey, const char *certpath)
+{
+ Identity *id;
+ int r;
+ struct sshkey *cert;
+
+ id = xcalloc(1, sizeof(Identity));
+ TAILQ_INSERT_TAIL(&idtab->idlist, id, next);
+ idtab->nentries++;
+ id->key = privkey_or_die(privkey);
+ id->comment = xstrdup("rhododaktulos Eos");
+ if (sshkey_is_sk(id->key))
+ id->sk_provider = xstrdup("internal");
+
+ /* Now the cert too */
+ id = xcalloc(1, sizeof(Identity));
+ TAILQ_INSERT_TAIL(&idtab->idlist, id, next);
+ idtab->nentries++;
+ id->key = privkey_or_die(privkey);
+ cert = pubkey_or_die(certpath);
+ if ((r = sshkey_to_certified(id->key)) != 0) {
+ error_fr(r, "sshkey_to_certified");
+ abort();
+ }
+ if ((r = sshkey_cert_copy(cert, id->key)) != 0) {
+ error_fr(r, "sshkey_cert_copy");
+ abort();
+ }
+ sshkey_free(cert);
+ id->comment = xstrdup("outis");
+ if (sshkey_is_sk(id->key))
+ id->sk_provider = xstrdup("internal");
+}
+
+static void
+cleanup_idtab(void)
+{
+ Identity *id;
+
+ if (idtab == NULL) return;
+ for (id = TAILQ_FIRST(&idtab->idlist); id;
+ id = TAILQ_FIRST(&idtab->idlist)) {
+ TAILQ_REMOVE(&idtab->idlist, id, next);
+ free_identity(id);
+ }
+ free(idtab);
+ idtab = NULL;
+}
+
+static void
+reset_idtab(void)
+{
+ cleanup_idtab();
+ idtab_init();
+ // Load keys.
+ add_key(PRIV_RSA, CERT_RSA);
+ add_key(PRIV_DSA, CERT_DSA);
+ add_key(PRIV_ECDSA, CERT_ECDSA);
+ add_key(PRIV_ED25519, CERT_ED25519);
+ add_key(PRIV_ECDSA_SK, CERT_ECDSA_SK);
+ add_key(PRIV_ED25519_SK, CERT_ED25519_SK);
+}
+
+static void
+cleanup_sockettab(void)
+{
+ u_int i;
+ for (i = 0; i < sockets_alloc; i++) {
+ if (sockets[i].type != AUTH_UNUSED)
+ close_socket(sockets + i);
+ }
+ free(sockets);
+ sockets = NULL;
+ sockets_alloc = 0;
+}
+
+static void
+reset_sockettab(int devnull)
+{
+ int fd;
+
+ cleanup_sockettab();
+ if ((fd = dup(devnull)) == -1) {
+ error_f("dup: %s", strerror(errno));
+ abort();
+ }
+ new_socket(AUTH_CONNECTION, fd);
+ assert(sockets[0].type == AUTH_CONNECTION);
+ assert(sockets[0].fd == fd);
+}
+
+#define MAX_MESSAGES 256
+void
+test_one(const uint8_t* s, size_t slen)
+{
+ static int devnull = -1;
+ size_t i, olen, nlen;
+
+ if (devnull == -1) {
+ log_init(__progname, SYSLOG_LEVEL_DEBUG3,
+ SYSLOG_FACILITY_AUTH, 1);
+ devnull = devnull_or_die();
+ allowed_providers = xstrdup("");
+ setenv("DISPLAY", "", 1); /* ban askpass */
+ }
+
+ reset_idtab();
+ reset_sockettab(devnull);
+ (void)sshbuf_put(sockets[0].input, s, slen);
+ for (i = 0; i < MAX_MESSAGES; i++) {
+ olen = sshbuf_len(sockets[0].input);
+ process_message(0);
+ nlen = sshbuf_len(sockets[0].input);
+ if (nlen == 0 || nlen == olen)
+ break;
+ }
+ cleanup_idtab();
+ cleanup_sockettab();
+}
diff --git a/regress/misc/fuzz-harness/fixed-keys.h b/regress/misc/fuzz-harness/fixed-keys.h
new file mode 100644
index 000000000..c6e7c6cc1
--- /dev/null
+++ b/regress/misc/fuzz-harness/fixed-keys.h
@@ -0,0 +1,119 @@
+/*
+ * Some keys used by fuzzers
+ */
+
+#define PRIV_RSA \
+"-----BEGIN OPENSSH PRIVATE KEY-----\n"\
+"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn\n"\
+"NhAAAAAwEAAQAAAQEA3+epf+VGKoGPaAZXrf6S0cyumQnddkGBnVFX0A5eh37RtLug0qY5\n"\
+"thxsBUbGGVr9mTd2QXwLujBwYg5l1MP/Fmg+5312Zgx9pHmS+qKULbar0hlNgptNEb+aNU\n"\
+"d3o9qg3aXqXm7+ZnjAV05ef/mxNRN2ZvuEkw7cRppTJcbBI+vF3lXuCXnX2klDI95Gl2AW\n"\
+"3WHRtanqLHZXuBkjjRBDKc7MUq/GP1hmLiAd95dvU7fZjRlIEsP84zGEI1Fb0L/kmPHcOt\n"\
+"iVfHft8CtmC9v6+94JrOiPBBNScV+dyrgAGPsdKdr/1vIpQmCNiI8s3PCiD8J7ZiBaYm0I\n"\
+"8fq5G/qnUwAAA7ggw2dXIMNnVwAAAAdzc2gtcnNhAAABAQDf56l/5UYqgY9oBlet/pLRzK\n"\
+"6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZm\n"\
+"DH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGml\n"\
+"MlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29T\n"\
+"t9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v\n"\
+"/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdTAAAAAwEAAQAAAQEArWm5B4tFasppjUHM\n"\
+"SsAuajtCxtizI1Hc10EW59cZM4vvUzE2f6+qZvdgWj3UU/L7Et23w0QVuSCnCerox379ZB\n"\
+"ddEOFFAAiQjwBx65hbd4RRUymxtIQfjq18++LcMJW1nbVQ7c69ThQbtALIggmbS+ZE/8Gx\n"\
+"jkwmIrCH0Ww8TlpsPe+mNHuyNk7UEZoXLm22lNLqq5qkIL5JgT6M2iNJpMOJy9/CKi6kO4\n"\
+"JPuVwjdG4C5pBPaMN3KJ1IvAlSlLGNaXnfXcn85gWfsCjsZmH3liey2NJamqp/w83BrKUg\n"\
+"YZvMR2qeWZaKkFTahpzN5KRK1BFeB37O0P84Dzh1biDX8QAAAIEAiWXW8ePYFwLpa2mFIh\n"\
+"VvRTdcrN70rVK5eWVaL3pyS4vGA56Jixq86dHveOnbSY+iNb1jQidtXc8SWUt2wtHqZ32h\n"\
+"Lji9/hMSKqe9SEP3xvDRDmUJqsVw0ySyrFrzm4160QY6RKU3CIQCVFslMZ9fxmrfZ/hxoU\n"\
+"0X3FVsxmC4+kwAAACBAPOc1YERpV6PjANBrGR+1o1RCdACbm5myc42QzSNIaOZmgrYs+Gt\n"\
+"7+EcoqSdbJzHJNCNQfF+A+vjbIkFiuZqq/5wwr59qXx5OAlijLB/ywwKmTWq6lp//Zxny+\n"\
+"ka3sIGNO14eQvmxNDnlLL+RIZleCTEKBXSW6CZhr+uHMZFKKMtAAAAgQDrSkm+LbILB7H9\n"\
+"jxEBZLhv53aAn4u81kFKQOJ7PzzpBGSoD12i7oIJu5siSD5EKDNVEr+SvCf0ISU3BuMpzl\n"\
+"t3YrPrHRheOFhn5e3j0e//zB8rBC0DGB4CtTDdeh7rOXUL4K0pz+8wEpNkV62SWxhC6NRW\n"\
+"I79JhtGkh+GtcnkEfwAAAAAB\n"\
+"-----END OPENSSH PRIVATE KEY-----\n"
+#define PUB_RSA \
+"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf56l/5UYqgY9oBlet/pLRzK6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZmDH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGmlMlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29Tt9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdT"
+#define CERT_RSA \
+"ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg89JX6OBMYDSxER8fnU5y8xxeMCHR/hI0uVqdEhNyCpcAAAADAQABAAABAQDf56l/5UYqgY9oBlet/pLRzK6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZmDH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGmlMlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29Tt9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdTAAAAAAAAA+0AAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQGCDA6PWw4x9bHQl0w7NqifHepumqD3dmyMx+hZGuPRon+TsyCjfytu7hWmV7l9XUF0fPQNFQ7FGat5e+7YUNgE= id_rsa.pub"
+#define PRIV_DSA \
+"-----BEGIN OPENSSH PRIVATE KEY-----\n"\
+"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsgAAAAdzc2gtZH\n"\
+"NzAAAAgQCsGTfjpQ465EOkfQXJM9BOvfRQE0fqlykAls+ncz+T7hrbeScRu8xpwzsznJNm\n"\
+"xlW8o6cUDiHmBJ5OHgamUC9N7YJeU/6fnOAZifgN8mqK6k8pKHuje8ANOiYgHLl0yiASQA\n"\
+"3//qMyzZ+W/hemoLSmLAbEqlfWVeyYx+wta1Vm+QAAABUAvWyehvUvdHvQxavYgS5p0t5Q\n"\
+"d7UAAACBAIRA9Yy+f4Kzqpv/qICPO3zk42UuP7WAhSW2nCbQdLlCiSTxcjKgcvXNRckwJP\n"\
+"44JjSHOtJy/AMtJrPIbLYG6KuWTdBlEHFiG6DafvLG+qPMSL2bPjXTOhuOMbCHIZ+5WBkW\n"\
+"THeG/Nv11iI01Of9V6tXkig23K370flkRkXFi9MdAAAAgCt6YUcQkNwG7B/e5M1FZsLP9O\n"\
+"kVB3BwLAOjmWdHpyhu3HpwSJa3XLEvhXN0i6IVI2KgPo/2GtYA6rHt14L+6u1pmhh8sAvQ\n"\
+"ksp3qZB+xh/NP+hBqf0sbHX0yYbzKOvI5SCc/kKK6yagcBZOsubM/KC8TxyVgmD5c6WzYs\n"\
+"h5TEpvAAAB2PHjRbbx40W2AAAAB3NzaC1kc3MAAACBAKwZN+OlDjrkQ6R9Bckz0E699FAT\n"\
+"R+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4B\n"\
+"mJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1r\n"\
+"VWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS\n"\
+"4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIb\n"\
+"oNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRc\n"\
+"WL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SL\n"\
+"ohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJ\n"\
+"z+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8AAAAUUA+OGldMi76ClO/sstpdbBUE\n"\
+"lq8AAAAAAQI=\n"\
+"-----END OPENSSH PRIVATE KEY-----\n"
+#define PUB_DSA \
+"ssh-dss AAAAB3NzaC1kc3MAAACBAKwZN+OlDjrkQ6R9Bckz0E699FATR+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4BmJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1rVWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIboNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRcWL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SLohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJz+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8="
+#define CERT_DSA \
+"ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAguF716Yub+vVKNlONKLsfxGYWkRe/PyjfYdGRTsFaDvAAAACBAKwZN+OlDjrkQ6R9Bckz0E699FATR+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4BmJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1rVWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIboNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRcWL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SLohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJz+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8AAAAAAAAD6AAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAjMQEZcbdUYJBjIC4GxByFDOb8tv71vDZdx7irHwaqIjx5rzpJUuOV1r8ZO4kY+Yaiun1yrWj2QYkfJrHBvD1DA== id_dsa.pub"
+#define PRIV_ECDSA \
+"-----BEGIN OPENSSH PRIVATE KEY-----\n"\
+"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS\n"\
+"1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTDJ0VlMv+0rguNzaJ1DF2KueHaxRSQ\n"\
+"6LpIxGbulrg1a8RPbnMXwag5GcDiDllD2lDUJUuBEWyjXA0rZoZX35ELAAAAoE/Bbr5PwW\n"\
+"6+AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43N\n"\
+"onUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQ\n"\
+"sAAAAhAIhE6hCID5oOm1TDktc++KFKyScjLifcZ6Cgv5xSSyLOAAAAAAECAwQFBgc=\n"\
+"-----END OPENSSH PRIVATE KEY-----\n"
+#define PUB_ECDSA \
+"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43NonUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQs="
+#define CERT_ECDSA \
+"ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgVJZuM/1AOe6n++qRWMyUuAThYqLvvQxj5CGflLODp60AAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43NonUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQsAAAAAAAAD6QAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAtdJpcF6ZmQL+ueices4QZeL7AK8Xuo08jyLgiolhjKy2jj4LSUki4aX/ZeZeJuby1ovGrfaeFAgx3itPLR7IAQ== id_ecdsa.pub"
+#define PRIV_ED25519 \
+"-----BEGIN OPENSSH PRIVATE KEY-----\n"\
+"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW\n"\
+"QyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAIhWlP99VpT/\n"\
+"fQAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAw\n"\
+"AAAEDE1rlcMC0s0X3TKVZAOVavZOywwkXw8tO5dLObxaCMEDPQXmEVMVLmeFRyafKMVWgP\n"\
+"Dkv8/uRBTwmcEDatZzMDAAAAAAECAwQF\n"\
+"-----END OPENSSH PRIVATE KEY-----\n"
+#define PUB_ED25519 \
+"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMD"
+#define CERT_ED25519 \
+"ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIMDQjYH6XRzH3j3MW1DdjCoAfvrHfgjnVGF+sLK0pBfqAAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMDAAAAAAAAA+sAAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQBj0og+s09/HpwdHZbzN0twooKPDWWrxGfnP1Joy6cDnY2BCSQ7zg9vbq11kLF8H/sKOTZWAQrUZ7LlChOu9Ogw= id_ed25519.pub"
+#define PRIV_ECDSA_SK \
+"-----BEGIN OPENSSH PRIVATE KEY-----\n"\
+"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2\n"\
+"RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQTYyU76zop1\n"\
+"VOb4DfKWYnR5b0TOC3zw8DzObAfHWB5o6xls+tOYiEleXvIEi00Da2iCK47habZTOhLyeB\n"\
+"X2Avu5AAAABHNzaDoAAAGYqUAQSKlAEEgAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv\n"\
+"cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEE2MlO+s6KdVTm+A3ylmJ0eW9Ezgt88PA8zm\n"\
+"wHx1geaOsZbPrTmIhJXl7yBItNA2togiuO4Wm2UzoS8ngV9gL7uQAAAARzc2g6AQAAAOMt\n"\
+"LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJSHFsZjNsWTkxZFhwUn\n"\
+"dYZDBrS0lYWmNpeDRRcDBNSU15Ny9JMUxXSTFuWG9Bb0dDQ3FHU000OQpBd0VIb1VRRFFn\n"\
+"QUUyTWxPK3M2S2RWVG0rQTN5bG1KMGVXOUV6Z3Q4OFBBOHptd0h4MWdlYU9zWmJQclRtSW\n"\
+"hKClhsN3lCSXROQTJ0b2dpdU80V20yVXpvUzhuZ1Y5Z0w3dVE9PQotLS0tLUVORCBFQyBQ\n"\
+"UklWQVRFIEtFWS0tLS0tCgAAAAAAAAAbZGptQGRqbS5zeWQuY29ycC5nb29nbGUuY29tAQ\n"\
+"IDBAUG\n"\
+"-----END OPENSSH PRIVATE KEY-----\n"
+#define PUB_ECDSA_SK \
+"sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBNjJTvrOinVU5vgN8pZidHlvRM4LfPDwPM5sB8dYHmjrGWz605iISV5e8gSLTQNraIIrjuFptlM6EvJ4FfYC+7kAAAAEc3NoOg=="
+#define CERT_ECDSA_SK \
+"sk-ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAK3NrLWVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgKLHtIca++5VoDrUAXU/KqGJZ7jZEnuJSTvt7VrYY9foAAAAIbmlzdHAyNTYAAABBBNjJTvrOinVU5vgN8pZidHlvRM4LfPDwPM5sB8dYHmjrGWz605iISV5e8gSLTQNraIIrjuFptlM6EvJ4FfYC+7kAAAAEc3NoOgAAAAAAAAPqAAAAAQAAAAd1bHlzc2VzAAAAFwAAAAd1bHlzc2VzAAAACG9keXNzZXVzAAAAAAAAAAD//////////wAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMDAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEB1naZOQDLaDr+fwn6E9x8/8HeiaUubDzPexfNQMz+m/7RD0gd5uJhHYUfDb5+/sIx1I7bUEeRIDkBbmZ2foo0E"
+#define PRIV_ED25519_SK \
+"-----BEGIN OPENSSH PRIVATE KEY-----\n"\
+"b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2\n"\
+"gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACCTJtH10vWhIDxd62edvMLg9u2cwYKyqa7332je\n"\
+"RArHjAAAAARzc2g6AAAAwN7vvE3e77xNAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2\n"\
+"9tAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDoBAAAAQEsS\n"\
+"xLFiVzfpH2mt9xh8i/zmHV646Hud4QruNBAGNl8gkybR9dL1oSA8XetnnbzC4PbtnMGCsq\n"\
+"mu999o3kQKx4wAAAAAAAAAG2RqbUBkam0uc3lkLmNvcnAuZ29vZ2xlLmNvbQECAwQFBg==\n"\
+"-----END OPENSSH PRIVATE KEY-----\n"
+#define PUB_ED25519_SK \
+"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDo="
+#define CERT_ED25519_SK \
+"sk-ssh-ed25519-cert-v01@openssh.com AAAAI3NrLXNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJiT+C/VLMWholFZ4xhOyJr0nSLZSFRIM3I07wUNTRPaAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDoAAAAAAAAD7AAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAX0Pu13B94pVR3qq8MJQGkOS1Cd7AAM1k6O2VSwyDPM/LfsWIQ4ywgxDmk3hjXWOY7BqljuMxo5VO4JymEIhQBA=="
diff --git a/regress/misc/fuzz-harness/kex_fuzz.cc b/regress/misc/fuzz-harness/kex_fuzz.cc
new file mode 100644
index 000000000..4740a7cb0
--- /dev/null
+++ b/regress/misc/fuzz-harness/kex_fuzz.cc
@@ -0,0 +1,461 @@
+// libfuzzer driver for key exchange fuzzing.
+
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern "C" {
+
+#include "includes.h"
+#include "ssherr.h"
+#include "ssh_api.h"
+#include "sshbuf.h"
+#include "packet.h"
+#include "myproposal.h"
+#include "xmalloc.h"
+#include "authfile.h"
+#include "log.h"
+
+#include "fixed-keys.h"
+
+// Define if you want to generate traces.
+/* #define STANDALONE 1 */
+
+static int prepare_key(struct shared_state *st, int keytype, int bits);
+
+struct shared_state {
+ size_t nkeys;
+ struct sshkey **privkeys, **pubkeys;
+};
+
+struct test_state {
+ struct sshbuf *smsgs, *cmsgs; /* output, for standalone mode */
+ struct sshbuf *sin, *cin; /* input; setup per-test in do_kex_with_key */
+ struct sshbuf *s_template, *c_template; /* main copy of input */
+};
+
+static int
+do_send_and_receive(struct ssh *from, struct ssh *to,
+ struct sshbuf *store, int clobber, size_t *n)
+{
+ u_char type;
+ size_t len;
+ const u_char *buf;
+ int r;
+
+ for (*n = 0;; (*n)++) {
+ if ((r = ssh_packet_next(from, &type)) != 0) {
+ debug_fr(r, "ssh_packet_next");
+ return r;
+ }
+ if (type != 0)
+ return 0;
+ buf = ssh_output_ptr(from, &len);
+ debug_f("%zu%s", len, clobber ? " ignore" : "");
+ if (len == 0)
+ return 0;
+ if ((r = ssh_output_consume(from, len)) != 0) {
+ debug_fr(r, "ssh_output_consume");
+ return r;
+ }
+ if (store != NULL && (r = sshbuf_put(store, buf, len)) != 0) {
+ debug_fr(r, "sshbuf_put");
+ return r;
+ }
+ if (!clobber && (r = ssh_input_append(to, buf, len)) != 0) {
+ debug_fr(r, "ssh_input_append");
+ return r;
+ }
+ }
+}
+
+static int
+run_kex(struct test_state *ts, struct ssh *client, struct ssh *server)
+{
+ int r = 0;
+ size_t cn, sn;
+
+ /* If fuzzing, replace server/client input */
+ if (ts->sin != NULL) {
+ if ((r = ssh_input_append(server, sshbuf_ptr(ts->sin),
+ sshbuf_len(ts->sin))) != 0) {
+ error_fr(r, "ssh_input_append");
+ return r;
+ }
+ sshbuf_reset(ts->sin);
+ }
+ if (ts->cin != NULL) {
+ if ((r = ssh_input_append(client, sshbuf_ptr(ts->cin),
+ sshbuf_len(ts->cin))) != 0) {
+ error_fr(r, "ssh_input_append");
+ return r;
+ }
+ sshbuf_reset(ts->cin);
+ }
+ while (!server->kex->done || !client->kex->done) {
+ cn = sn = 0;
+ debug_f("S:");
+ if ((r = do_send_and_receive(server, client,
+ ts->smsgs, ts->cin != NULL, &sn)) != 0) {
+ debug_fr(r, "S->C");
+ break;
+ }
+ debug_f("C:");
+ if ((r = do_send_and_receive(client, server,
+ ts->cmsgs, ts->sin != NULL, &cn)) != 0) {
+ debug_fr(r, "C->S");
+ break;
+ }
+ if (cn == 0 && sn == 0) {
+ debug_f("kex stalled");
+ r = SSH_ERR_PROTOCOL_ERROR;
+ break;
+ }
+ }
+ debug_fr(r, "done");
+ return r;
+}
+
+static void
+store_key(struct shared_state *st, struct sshkey *pubkey,
+ struct sshkey *privkey)
+{
+ if (st == NULL || pubkey->type < 0 || pubkey->type > INT_MAX ||
+ privkey->type != pubkey->type ||
+ ((size_t)pubkey->type < st->nkeys &&
+ st->pubkeys[pubkey->type] != NULL))
+ abort();
+ if ((size_t)pubkey->type >= st->nkeys) {
+ st->pubkeys = (struct sshkey **)xrecallocarray(st->pubkeys,
+ st->nkeys, pubkey->type + 1, sizeof(*st->pubkeys));
+ st->privkeys = (struct sshkey **)xrecallocarray(st->privkeys,
+ st->nkeys, privkey->type + 1, sizeof(*st->privkeys));
+ st->nkeys = privkey->type + 1;
+ }
+ debug_f("store %s at %d", sshkey_ssh_name(pubkey), pubkey->type);
+ st->pubkeys[pubkey->type] = pubkey;
+ st->privkeys[privkey->type] = privkey;
+}
+
+static int
+prepare_keys(struct shared_state *st)
+{
+ if (prepare_key(st, KEY_RSA, 2048) != 0 ||
+ prepare_key(st, KEY_DSA, 1024) != 0 ||
+ prepare_key(st, KEY_ECDSA, 256) != 0 ||
+ prepare_key(st, KEY_ED25519, 256) != 0) {
+ error_f("key prepare failed");
+ return -1;
+ }
+ return 0;
+}
+
+static struct sshkey *
+get_pubkey(struct shared_state *st, int keytype)
+{
+ if (st == NULL || keytype < 0 || (size_t)keytype >= st->nkeys ||
+ st->pubkeys == NULL || st->pubkeys[keytype] == NULL)
+ abort();
+ return st->pubkeys[keytype];
+}
+
+static struct sshkey *
+get_privkey(struct shared_state *st, int keytype)
+{
+ if (st == NULL || keytype < 0 || (size_t)keytype >= st->nkeys ||
+ st->privkeys == NULL || st->privkeys[keytype] == NULL)
+ abort();
+ return st->privkeys[keytype];
+}
+
+static int
+do_kex_with_key(struct shared_state *st, struct test_state *ts,
+ const char *kex, int keytype)
+{
+ struct ssh *client = NULL, *server = NULL;
+ struct sshkey *privkey = NULL, *pubkey = NULL;
+ struct sshbuf *state = NULL;
+ struct kex_params kex_params;
+ const char *ccp, *proposal[PROPOSAL_MAX] = { KEX_CLIENT };
+ char *myproposal[PROPOSAL_MAX] = {0}, *keyname = NULL;
+ int i, r;
+
+ ts->cin = ts->sin = NULL;
+ if (ts->c_template != NULL &&
+ (ts->cin = sshbuf_fromb(ts->c_template)) == NULL)
+ abort();
+ if (ts->s_template != NULL &&
+ (ts->sin = sshbuf_fromb(ts->s_template)) == NULL)
+ abort();
+
+ pubkey = get_pubkey(st, keytype);
+ privkey = get_privkey(st, keytype);
+ keyname = xstrdup(sshkey_ssh_name(privkey));
+ if (ts->cin != NULL) {
+ debug_f("%s %s clobber client %zu", kex, keyname,
+ sshbuf_len(ts->cin));
+ } else if (ts->sin != NULL) {
+ debug_f("%s %s clobber server %zu", kex, keyname,
+ sshbuf_len(ts->sin));
+ } else
+ debug_f("%s %s noclobber", kex, keyname);
+
+ for (i = 0; i < PROPOSAL_MAX; i++) {
+ ccp = proposal[i];
+#ifdef CIPHER_NONE_AVAIL
+ if (i == PROPOSAL_ENC_ALGS_CTOS || i == PROPOSAL_ENC_ALGS_STOC)
+ ccp = "none";
+#endif
+ if (i == PROPOSAL_SERVER_HOST_KEY_ALGS)
+ ccp = keyname;
+ else if (i == PROPOSAL_KEX_ALGS && kex != NULL)
+ ccp = kex;
+ if ((myproposal[i] = strdup(ccp)) == NULL) {
+ error_f("strdup prop %d", i);
+ goto fail;
+ }
+ }
+ memcpy(kex_params.proposal, myproposal, sizeof(myproposal));
+ if ((r = ssh_init(&client, 0, &kex_params)) != 0) {
+ error_fr(r, "init client");
+ goto fail;
+ }
+ if ((r = ssh_init(&server, 1, &kex_params)) != 0) {
+ error_fr(r, "init server");
+ goto fail;
+ }
+ if ((r = ssh_add_hostkey(server, privkey)) != 0 ||
+ (r = ssh_add_hostkey(client, pubkey)) != 0) {
+ error_fr(r, "add hostkeys");
+ goto fail;
+ }
+ if ((r = run_kex(ts, client, server)) != 0) {
+ error_fr(r, "kex");
+ goto fail;
+ }
+ /* XXX rekex, set_state, etc */
+ fail:
+ for (i = 0; i < PROPOSAL_MAX; i++)
+ free(myproposal[i]);
+ sshbuf_free(ts->sin);
+ sshbuf_free(ts->cin);
+ sshbuf_free(state);
+ ssh_free(client);
+ ssh_free(server);
+ free(keyname);
+ return r;
+}
+
+static int
+prepare_key(struct shared_state *st, int kt, int bits)
+{
+ const char *pubstr = NULL;
+ const char *privstr = NULL;
+ char *tmp, *cp;
+ struct sshkey *privkey = NULL, *pubkey = NULL;
+ struct sshbuf *b = NULL;
+ int r;
+
+ switch (kt) {
+ case KEY_RSA:
+ pubstr = PUB_RSA;
+ privstr = PRIV_RSA;
+ break;
+ case KEY_DSA:
+ pubstr = PUB_DSA;
+ privstr = PRIV_DSA;
+ break;
+ case KEY_ECDSA:
+ pubstr = PUB_ECDSA;
+ privstr = PRIV_ECDSA;
+ break;
+ case KEY_ED25519:
+ pubstr = PUB_ED25519;
+ privstr = PRIV_ED25519;
+ break;
+ default:
+ abort();
+ }
+ if ((b = sshbuf_from(privstr, strlen(privstr))) == NULL)
+ abort();
+ if ((r = sshkey_parse_private_fileblob(b, "", &privkey, NULL)) != 0) {
+ error_fr(r, "priv %d", kt);
+ abort();
+ }
+ sshbuf_free(b);
+ tmp = cp = xstrdup(pubstr);
+ if ((pubkey = sshkey_new(KEY_UNSPEC)) == NULL)
+ abort();
+ if ((r = sshkey_read(pubkey, &cp)) != 0) {
+ error_fr(r, "pub %d", kt);
+ abort();
+ }
+ free(tmp);
+
+ store_key(st, pubkey, privkey);
+ return 0;
+}
+
+#if defined(STANDALONE)
+
+#if 0 /* use this if generating new keys to embed above */
+static int
+prepare_key(struct shared_state *st, int keytype, int bits)
+{
+ struct sshkey *privkey = NULL, *pubkey = NULL;
+ int r;
+
+ if ((r = sshkey_generate(keytype, bits, &privkey)) != 0) {
+ error_fr(r, "generate");
+ abort();
+ }
+ if ((r = sshkey_from_private(privkey, &pubkey)) != 0) {
+ error_fr(r, "make pubkey");
+ abort();
+ }
+ store_key(st, pubkey, privkey);
+ return 0;
+}
+#endif
+
+int main(void)
+{
+ static struct shared_state *st;
+ struct test_state *ts;
+ const int keytypes[] = { KEY_RSA, KEY_DSA, KEY_ECDSA, KEY_ED25519, -1 };
+ const char *kextypes[] = {
+ "sntrup761x25519-sha512@openssh.com",
+ "curve25519-sha256@libssh.org",
+ "ecdh-sha2-nistp256",
+ "diffie-hellman-group1-sha1",
+ "diffie-hellman-group-exchange-sha1",
+ NULL,
+ };
+ int i, j;
+ char *path;
+ FILE *f;
+
+ log_init("kex_fuzz", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 1);
+
+ if (st == NULL) {
+ st = (struct shared_state *)xcalloc(1, sizeof(*st));
+ prepare_keys(st);
+ }
+ /* Run each kex method for each key and save client/server packets */
+ for (i = 0; keytypes[i] != -1; i++) {
+ for (j = 0; kextypes[j] != NULL; j++) {
+ ts = (struct test_state *)xcalloc(1, sizeof(*ts));
+ ts->smsgs = sshbuf_new();
+ ts->cmsgs = sshbuf_new();
+ do_kex_with_key(st, ts, kextypes[j], keytypes[i]);
+ xasprintf(&path, "S2C-%s-%s",
+ kextypes[j], sshkey_type(st->pubkeys[keytypes[i]]));
+ debug_f("%s", path);
+ if ((f = fopen(path, "wb+")) == NULL)
+ abort();
+ if (fwrite(sshbuf_ptr(ts->smsgs), 1,
+ sshbuf_len(ts->smsgs), f) != sshbuf_len(ts->smsgs))
+ abort();
+ fclose(f);
+ free(path);
+ //sshbuf_dump(ts->smsgs, stderr);
+ xasprintf(&path, "C2S-%s-%s",
+ kextypes[j], sshkey_type(st->pubkeys[keytypes[i]]));
+ debug_f("%s", path);
+ if ((f = fopen(path, "wb+")) == NULL)
+ abort();
+ if (fwrite(sshbuf_ptr(ts->cmsgs), 1,
+ sshbuf_len(ts->cmsgs), f) != sshbuf_len(ts->cmsgs))
+ abort();
+ fclose(f);
+ free(path);
+ //sshbuf_dump(ts->cmsgs, stderr);
+ sshbuf_free(ts->smsgs);
+ sshbuf_free(ts->cmsgs);
+ free(ts);
+ }
+ }
+ for (i = 0; keytypes[i] != -1; i++) {
+ xasprintf(&path, "%s.priv",
+ sshkey_type(st->privkeys[keytypes[i]]));
+ debug_f("%s", path);
+ if (sshkey_save_private(st->privkeys[keytypes[i]], path,
+ "", "", SSHKEY_PRIVATE_OPENSSH, NULL, 0) != 0)
+ abort();
+ free(path);
+ xasprintf(&path, "%s.pub",
+ sshkey_type(st->pubkeys[keytypes[i]]));
+ debug_f("%s", path);
+ if (sshkey_save_public(st->pubkeys[keytypes[i]], path, "") != 0)
+ abort();
+ free(path);
+ }
+}
+#else /* !STANDALONE */
+static void
+do_kex(struct shared_state *st, struct test_state *ts, const char *kex)
+{
+ do_kex_with_key(st, ts, kex, KEY_RSA);
+ do_kex_with_key(st, ts, kex, KEY_DSA);
+ do_kex_with_key(st, ts, kex, KEY_ECDSA);
+ do_kex_with_key(st, ts, kex, KEY_ED25519);
+}
+
+static void
+kex_tests(struct shared_state *st, struct test_state *ts)
+{
+ do_kex(st, ts, "sntrup761x25519-sha512@openssh.com");
+ do_kex(st, ts, "curve25519-sha256@libssh.org");
+ do_kex(st, ts, "ecdh-sha2-nistp256");
+ do_kex(st, ts, "diffie-hellman-group1-sha1");
+ do_kex(st, ts, "diffie-hellman-group-exchange-sha1");
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
+{
+ static struct shared_state *st;
+ struct test_state *ts;
+ u_char crbuf[SSH_MAX_PRE_BANNER_LINES * 4];
+ u_char zbuf[4096] = {0};
+ static LogLevel loglevel = SYSLOG_LEVEL_INFO;
+
+ if (st == NULL) {
+ if (getenv("DEBUG") != NULL || getenv("KEX_FUZZ_DEBUG") != NULL)
+ loglevel = SYSLOG_LEVEL_DEBUG3;
+ log_init("kex_fuzz",
+ loglevel, SYSLOG_FACILITY_AUTH, 1);
+ st = (struct shared_state *)xcalloc(1, sizeof(*st));
+ prepare_keys(st);
+ }
+
+ /* Ensure that we can complete (fail) banner exchange at least */
+ memset(crbuf, '\n', sizeof(crbuf));
+
+ ts = (struct test_state *)xcalloc(1, sizeof(*ts));
+ if ((ts->s_template = sshbuf_new()) == NULL ||
+ sshbuf_put(ts->s_template, data, size) != 0 ||
+ sshbuf_put(ts->s_template, crbuf, sizeof(crbuf)) != 0 ||
+ sshbuf_put(ts->s_template, zbuf, sizeof(zbuf)) != 0)
+ abort();
+ kex_tests(st, ts);
+ sshbuf_free(ts->s_template);
+ free(ts);
+
+ ts = (struct test_state *)xcalloc(1, sizeof(*ts));
+ if ((ts->c_template = sshbuf_new()) == NULL ||
+ sshbuf_put(ts->c_template, data, size) != 0 ||
+ sshbuf_put(ts->c_template, crbuf, sizeof(crbuf)) != 0 ||
+ sshbuf_put(ts->c_template, zbuf, sizeof(zbuf)) != 0)
+ abort();
+ kex_tests(st, ts);
+ sshbuf_free(ts->c_template);
+ free(ts);
+
+ return 0;
+}
+#endif /* STANDALONE */
+} /* extern "C" */
diff --git a/regress/misc/fuzz-harness/testdata/README b/regress/misc/fuzz-harness/testdata/README
new file mode 100644
index 000000000..752053001
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/README
@@ -0,0 +1,4 @@
+This is preparatory data for fuzzing testing including scripts and test keys,
+corresponding to ../fixed-keys that are used in the fuzz tests and consequent
+fuzzing seed corpora. They should not be changed unless the affected seed
+corpora are also regenerated.
diff --git a/regress/misc/fuzz-harness/testdata/create-agent-corpus.sh b/regress/misc/fuzz-harness/testdata/create-agent-corpus.sh
new file mode 100755
index 000000000..1043b9ff4
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/create-agent-corpus.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+# Exercise ssh-agent to generate fuzzing corpus
+
+# XXX assumes agent hacked up with sk-dummy.o and ssh-sk.o linked directly
+# and dumping of e->request for each message.
+
+set -xe
+SSH_AUTH_SOCK=$PWD/sock
+rm -f agent-[0-9]* $SSH_AUTH_SOCK
+export SSH_AUTH_SOCK
+../../../../ssh-agent -D -a $SSH_AUTH_SOCK &
+sleep 1
+AGENT_PID=$!
+trap "kill $AGENT_PID" EXIT
+
+PRIV="id_dsa id_ecdsa id_ecdsa_sk id_ed25519 id_ed25519_sk id_rsa"
+
+# add keys
+ssh-add $PRIV
+
+# sign
+ssh-add -T *.pub
+
+# list
+ssh-add -l
+
+# remove individually
+ssh-add -d $PRIV
+
+# re-add with constraints
+ssh-add -c -t 3h $PRIV
+
+# delete all
+ssh-add -D
+
+# attempt to add a PKCS#11 token
+ssh-add -s /fake || :
+
+# attempt to delete PKCS#11
+ssh-add -e /fake || :
+
+ssh-add -L
+
diff --git a/regress/misc/fuzz-harness/testdata/id_dsa b/regress/misc/fuzz-harness/testdata/id_dsa
new file mode 100644
index 000000000..88bf5566c
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/id_dsa
@@ -0,0 +1,21 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABsgAAAAdzc2gtZH
+NzAAAAgQCsGTfjpQ465EOkfQXJM9BOvfRQE0fqlykAls+ncz+T7hrbeScRu8xpwzsznJNm
+xlW8o6cUDiHmBJ5OHgamUC9N7YJeU/6fnOAZifgN8mqK6k8pKHuje8ANOiYgHLl0yiASQA
+3//qMyzZ+W/hemoLSmLAbEqlfWVeyYx+wta1Vm+QAAABUAvWyehvUvdHvQxavYgS5p0t5Q
+d7UAAACBAIRA9Yy+f4Kzqpv/qICPO3zk42UuP7WAhSW2nCbQdLlCiSTxcjKgcvXNRckwJP
+44JjSHOtJy/AMtJrPIbLYG6KuWTdBlEHFiG6DafvLG+qPMSL2bPjXTOhuOMbCHIZ+5WBkW
+THeG/Nv11iI01Of9V6tXkig23K370flkRkXFi9MdAAAAgCt6YUcQkNwG7B/e5M1FZsLP9O
+kVB3BwLAOjmWdHpyhu3HpwSJa3XLEvhXN0i6IVI2KgPo/2GtYA6rHt14L+6u1pmhh8sAvQ
+ksp3qZB+xh/NP+hBqf0sbHX0yYbzKOvI5SCc/kKK6yagcBZOsubM/KC8TxyVgmD5c6WzYs
+h5TEpvAAAB2PHjRbbx40W2AAAAB3NzaC1kc3MAAACBAKwZN+OlDjrkQ6R9Bckz0E699FAT
+R+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4B
+mJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1r
+VWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS
+4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIb
+oNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRc
+WL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SL
+ohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJ
+z+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8AAAAUUA+OGldMi76ClO/sstpdbBUE
+lq8AAAAAAQI=
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/misc/fuzz-harness/testdata/id_dsa-cert.pub b/regress/misc/fuzz-harness/testdata/id_dsa-cert.pub
new file mode 100644
index 000000000..3afb87fe6
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/id_dsa-cert.pub
@@ -0,0 +1 @@
+ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAguF716Yub+vVKNlONKLsfxGYWkRe/PyjfYdGRTsFaDvAAAACBAKwZN+OlDjrkQ6R9Bckz0E699FATR+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4BmJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1rVWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIboNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRcWL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SLohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJz+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8AAAAAAAAD6AAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAjMQEZcbdUYJBjIC4GxByFDOb8tv71vDZdx7irHwaqIjx5rzpJUuOV1r8ZO4kY+Yaiun1yrWj2QYkfJrHBvD1DA== id_dsa.pub
diff --git a/regress/misc/fuzz-harness/testdata/id_dsa.pub b/regress/misc/fuzz-harness/testdata/id_dsa.pub
new file mode 100644
index 000000000..6f91c4e07
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/id_dsa.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAKwZN+OlDjrkQ6R9Bckz0E699FATR+qXKQCWz6dzP5PuGtt5JxG7zGnDOzOck2bGVbyjpxQOIeYEnk4eBqZQL03tgl5T/p+c4BmJ+A3yaorqTykoe6N7wA06JiAcuXTKIBJADf/+ozLNn5b+F6agtKYsBsSqV9ZV7JjH7C1rVWb5AAAAFQC9bJ6G9S90e9DFq9iBLmnS3lB3tQAAAIEAhED1jL5/grOqm/+ogI87fOTjZS4/tYCFJbacJtB0uUKJJPFyMqBy9c1FyTAk/jgmNIc60nL8Ay0ms8hstgboq5ZN0GUQcWIboNp+8sb6o8xIvZs+NdM6G44xsIchn7lYGRZMd4b82/XWIjTU5/1Xq1eSKDbcrfvR+WRGRcWL0x0AAACAK3phRxCQ3AbsH97kzUVmws/06RUHcHAsA6OZZ0enKG7cenBIlrdcsS+Fc3SLohUjYqA+j/Ya1gDqse3Xgv7q7WmaGHywC9CSynepkH7GH80/6EGp/SxsdfTJhvMo68jlIJz+QorrJqBwFk6y5sz8oLxPHJWCYPlzpbNiyHlMSm8=
diff --git a/regress/misc/fuzz-harness/testdata/id_ecdsa b/regress/misc/fuzz-harness/testdata/id_ecdsa
new file mode 100644
index 000000000..c1a96c6f9
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/id_ecdsa
@@ -0,0 +1,8 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
+1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTDJ0VlMv+0rguNzaJ1DF2KueHaxRSQ
+6LpIxGbulrg1a8RPbnMXwag5GcDiDllD2lDUJUuBEWyjXA0rZoZX35ELAAAAoE/Bbr5PwW
+6+AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43N
+onUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQ
+sAAAAhAIhE6hCID5oOm1TDktc++KFKyScjLifcZ6Cgv5xSSyLOAAAAAAECAwQFBgc=
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/misc/fuzz-harness/testdata/id_ecdsa-cert.pub b/regress/misc/fuzz-harness/testdata/id_ecdsa-cert.pub
new file mode 100644
index 000000000..9de599917
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/id_ecdsa-cert.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgVJZuM/1AOe6n++qRWMyUuAThYqLvvQxj5CGflLODp60AAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43NonUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQsAAAAAAAAD6QAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAtdJpcF6ZmQL+ueices4QZeL7AK8Xuo08jyLgiolhjKy2jj4LSUki4aX/ZeZeJuby1ovGrfaeFAgx3itPLR7IAQ== id_ecdsa.pub
diff --git a/regress/misc/fuzz-harness/testdata/id_ecdsa.pub b/regress/misc/fuzz-harness/testdata/id_ecdsa.pub
new file mode 100644
index 000000000..30a7cc23b
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/id_ecdsa.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMMnRWUy/7SuC43NonUMXYq54drFFJDoukjEZu6WuDVrxE9ucxfBqDkZwOIOWUPaUNQlS4ERbKNcDStmhlffkQs=
diff --git a/regress/misc/fuzz-harness/testdata/id_ecdsa_sk b/regress/misc/fuzz-harness/testdata/id_ecdsa_sk
new file mode 100644
index 000000000..5a364ed39
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/id_ecdsa_sk
@@ -0,0 +1,14 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2
+RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQTYyU76zop1
+VOb4DfKWYnR5b0TOC3zw8DzObAfHWB5o6xls+tOYiEleXvIEi00Da2iCK47habZTOhLyeB
+X2Avu5AAAABHNzaDoAAAGYqUAQSKlAEEgAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv
+cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEE2MlO+s6KdVTm+A3ylmJ0eW9Ezgt88PA8zm
+wHx1geaOsZbPrTmIhJXl7yBItNA2togiuO4Wm2UzoS8ngV9gL7uQAAAARzc2g6AQAAAOMt
+LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJSHFsZjNsWTkxZFhwUn
+dYZDBrS0lYWmNpeDRRcDBNSU15Ny9JMUxXSTFuWG9Bb0dDQ3FHU000OQpBd0VIb1VRRFFn
+QUUyTWxPK3M2S2RWVG0rQTN5bG1KMGVXOUV6Z3Q4OFBBOHptd0h4MWdlYU9zWmJQclRtSW
+hKClhsN3lCSXROQTJ0b2dpdU80V20yVXpvUzhuZ1Y5Z0w3dVE9PQotLS0tLUVORCBFQyBQ
+UklWQVRFIEtFWS0tLS0tCgAAAAAAAAAbZGptQGRqbS5zeWQuY29ycC5nb29nbGUuY29tAQ
+IDBAUG
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/misc/fuzz-harness/testdata/id_ecdsa_sk-cert.pub b/regress/misc/fuzz-harness/testdata/id_ecdsa_sk-cert.pub
new file mode 100644
index 000000000..14040fad7
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/id_ecdsa_sk-cert.pub
@@ -0,0 +1 @@
+sk-ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAK3NrLWVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgKLHtIca++5VoDrUAXU/KqGJZ7jZEnuJSTvt7VrYY9foAAAAIbmlzdHAyNTYAAABBBNjJTvrOinVU5vgN8pZidHlvRM4LfPDwPM5sB8dYHmjrGWz605iISV5e8gSLTQNraIIrjuFptlM6EvJ4FfYC+7kAAAAEc3NoOgAAAAAAAAPqAAAAAQAAAAd1bHlzc2VzAAAAFwAAAAd1bHlzc2VzAAAACG9keXNzZXVzAAAAAAAAAAD//////////wAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMDAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEB1naZOQDLaDr+fwn6E9x8/8HeiaUubDzPexfNQMz+m/7RD0gd5uJhHYUfDb5+/sIx1I7bUEeRIDkBbmZ2foo0E djm@djm.syd.corp.google.com
diff --git a/regress/misc/fuzz-harness/testdata/id_ecdsa_sk.pub b/regress/misc/fuzz-harness/testdata/id_ecdsa_sk.pub
new file mode 100644
index 000000000..1b5e829b7
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/id_ecdsa_sk.pub
@@ -0,0 +1 @@
+sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBNjJTvrOinVU5vgN8pZidHlvRM4LfPDwPM5sB8dYHmjrGWz605iISV5e8gSLTQNraIIrjuFptlM6EvJ4FfYC+7kAAAAEc3NoOg== djm@djm.syd.corp.google.com
diff --git a/regress/misc/fuzz-harness/testdata/id_ed25519 b/regress/misc/fuzz-harness/testdata/id_ed25519
new file mode 100644
index 000000000..6a7fbac92
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/id_ed25519
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAIhWlP99VpT/
+fQAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAw
+AAAEDE1rlcMC0s0X3TKVZAOVavZOywwkXw8tO5dLObxaCMEDPQXmEVMVLmeFRyafKMVWgP
+Dkv8/uRBTwmcEDatZzMDAAAAAAECAwQF
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/misc/fuzz-harness/testdata/id_ed25519-cert.pub b/regress/misc/fuzz-harness/testdata/id_ed25519-cert.pub
new file mode 100644
index 000000000..6a95fed2a
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/id_ed25519-cert.pub
@@ -0,0 +1 @@
+ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIMDQjYH6XRzH3j3MW1DdjCoAfvrHfgjnVGF+sLK0pBfqAAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMDAAAAAAAAA+sAAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQBj0og+s09/HpwdHZbzN0twooKPDWWrxGfnP1Joy6cDnY2BCSQ7zg9vbq11kLF8H/sKOTZWAQrUZ7LlChOu9Ogw= id_ed25519.pub
diff --git a/regress/misc/fuzz-harness/testdata/id_ed25519.pub b/regress/misc/fuzz-harness/testdata/id_ed25519.pub
new file mode 100644
index 000000000..87b617447
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/id_ed25519.pub
@@ -0,0 +1,2 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDPQXmEVMVLmeFRyafKMVWgPDkv8/uRBTwmcEDatZzMD
+
diff --git a/regress/misc/fuzz-harness/testdata/id_ed25519_sk b/regress/misc/fuzz-harness/testdata/id_ed25519_sk
new file mode 100644
index 000000000..9dcda6c46
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/id_ed25519_sk
@@ -0,0 +1,8 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2
+gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACCTJtH10vWhIDxd62edvMLg9u2cwYKyqa7332je
+RArHjAAAAARzc2g6AAAAwN7vvE3e77xNAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2
+9tAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDoBAAAAQEsS
+xLFiVzfpH2mt9xh8i/zmHV646Hud4QruNBAGNl8gkybR9dL1oSA8XetnnbzC4PbtnMGCsq
+mu999o3kQKx4wAAAAAAAAAG2RqbUBkam0uc3lkLmNvcnAuZ29vZ2xlLmNvbQECAwQFBg==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/misc/fuzz-harness/testdata/id_ed25519_sk-cert.pub b/regress/misc/fuzz-harness/testdata/id_ed25519_sk-cert.pub
new file mode 100644
index 000000000..9e41eec00
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/id_ed25519_sk-cert.pub
@@ -0,0 +1 @@
+sk-ssh-ed25519-cert-v01@openssh.com AAAAI3NrLXNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJiT+C/VLMWholFZ4xhOyJr0nSLZSFRIM3I07wUNTRPaAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDoAAAAAAAAD7AAAAAEAAAAHdWx5c3NlcwAAABcAAAAHdWx5c3NlcwAAAAhvZHlzc2V1cwAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACAz0F5hFTFS5nhUcmnyjFVoDw5L/P7kQU8JnBA2rWczAwAAAFMAAAALc3NoLWVkMjU1MTkAAABAX0Pu13B94pVR3qq8MJQGkOS1Cd7AAM1k6O2VSwyDPM/LfsWIQ4ywgxDmk3hjXWOY7BqljuMxo5VO4JymEIhQBA== djm@djm.syd.corp.google.com
diff --git a/regress/misc/fuzz-harness/testdata/id_ed25519_sk.pub b/regress/misc/fuzz-harness/testdata/id_ed25519_sk.pub
new file mode 100644
index 000000000..38d198444
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/id_ed25519_sk.pub
@@ -0,0 +1 @@
+sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJMm0fXS9aEgPF3rZ528wuD27ZzBgrKprvffaN5ECseMAAAABHNzaDo= djm@djm.syd.corp.google.com
diff --git a/regress/misc/fuzz-harness/testdata/id_rsa b/regress/misc/fuzz-harness/testdata/id_rsa
new file mode 100644
index 000000000..574fecf47
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/id_rsa
@@ -0,0 +1,27 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
+NhAAAAAwEAAQAAAQEA3+epf+VGKoGPaAZXrf6S0cyumQnddkGBnVFX0A5eh37RtLug0qY5
+thxsBUbGGVr9mTd2QXwLujBwYg5l1MP/Fmg+5312Zgx9pHmS+qKULbar0hlNgptNEb+aNU
+d3o9qg3aXqXm7+ZnjAV05ef/mxNRN2ZvuEkw7cRppTJcbBI+vF3lXuCXnX2klDI95Gl2AW
+3WHRtanqLHZXuBkjjRBDKc7MUq/GP1hmLiAd95dvU7fZjRlIEsP84zGEI1Fb0L/kmPHcOt
+iVfHft8CtmC9v6+94JrOiPBBNScV+dyrgAGPsdKdr/1vIpQmCNiI8s3PCiD8J7ZiBaYm0I
+8fq5G/qnUwAAA7ggw2dXIMNnVwAAAAdzc2gtcnNhAAABAQDf56l/5UYqgY9oBlet/pLRzK
+6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZm
+DH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGml
+MlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29T
+t9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v
+/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdTAAAAAwEAAQAAAQEArWm5B4tFasppjUHM
+SsAuajtCxtizI1Hc10EW59cZM4vvUzE2f6+qZvdgWj3UU/L7Et23w0QVuSCnCerox379ZB
+ddEOFFAAiQjwBx65hbd4RRUymxtIQfjq18++LcMJW1nbVQ7c69ThQbtALIggmbS+ZE/8Gx
+jkwmIrCH0Ww8TlpsPe+mNHuyNk7UEZoXLm22lNLqq5qkIL5JgT6M2iNJpMOJy9/CKi6kO4
+JPuVwjdG4C5pBPaMN3KJ1IvAlSlLGNaXnfXcn85gWfsCjsZmH3liey2NJamqp/w83BrKUg
+YZvMR2qeWZaKkFTahpzN5KRK1BFeB37O0P84Dzh1biDX8QAAAIEAiWXW8ePYFwLpa2mFIh
+VvRTdcrN70rVK5eWVaL3pyS4vGA56Jixq86dHveOnbSY+iNb1jQidtXc8SWUt2wtHqZ32h
+Lji9/hMSKqe9SEP3xvDRDmUJqsVw0ySyrFrzm4160QY6RKU3CIQCVFslMZ9fxmrfZ/hxoU
+0X3FVsxmC4+kwAAACBAPOc1YERpV6PjANBrGR+1o1RCdACbm5myc42QzSNIaOZmgrYs+Gt
+7+EcoqSdbJzHJNCNQfF+A+vjbIkFiuZqq/5wwr59qXx5OAlijLB/ywwKmTWq6lp//Zxny+
+ka3sIGNO14eQvmxNDnlLL+RIZleCTEKBXSW6CZhr+uHMZFKKMtAAAAgQDrSkm+LbILB7H9
+jxEBZLhv53aAn4u81kFKQOJ7PzzpBGSoD12i7oIJu5siSD5EKDNVEr+SvCf0ISU3BuMpzl
+t3YrPrHRheOFhn5e3j0e//zB8rBC0DGB4CtTDdeh7rOXUL4K0pz+8wEpNkV62SWxhC6NRW
+I79JhtGkh+GtcnkEfwAAAAAB
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/misc/fuzz-harness/testdata/id_rsa-cert.pub b/regress/misc/fuzz-harness/testdata/id_rsa-cert.pub
new file mode 100644
index 000000000..01761a38f
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/id_rsa-cert.pub
@@ -0,0 +1 @@
+ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg89JX6OBMYDSxER8fnU5y8xxeMCHR/hI0uVqdEhNyCpcAAAADAQABAAABAQDf56l/5UYqgY9oBlet/pLRzK6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZmDH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGmlMlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29Tt9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdTAAAAAAAAA+0AAAABAAAAB3VseXNzZXMAAAAXAAAAB3VseXNzZXMAAAAIb2R5c3NldXMAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAADMAAAALc3NoLWVkMjU1MTkAAAAgM9BeYRUxUuZ4VHJp8oxVaA8OS/z+5EFPCZwQNq1nMwMAAABTAAAAC3NzaC1lZDI1NTE5AAAAQGCDA6PWw4x9bHQl0w7NqifHepumqD3dmyMx+hZGuPRon+TsyCjfytu7hWmV7l9XUF0fPQNFQ7FGat5e+7YUNgE= id_rsa.pub
diff --git a/regress/misc/fuzz-harness/testdata/id_rsa.pub b/regress/misc/fuzz-harness/testdata/id_rsa.pub
new file mode 100644
index 000000000..05015e12b
--- /dev/null
+++ b/regress/misc/fuzz-harness/testdata/id_rsa.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDf56l/5UYqgY9oBlet/pLRzK6ZCd12QYGdUVfQDl6HftG0u6DSpjm2HGwFRsYZWv2ZN3ZBfAu6MHBiDmXUw/8WaD7nfXZmDH2keZL6opQttqvSGU2Cm00Rv5o1R3ej2qDdpepebv5meMBXTl5/+bE1E3Zm+4STDtxGmlMlxsEj68XeVe4JedfaSUMj3kaXYBbdYdG1qeosdle4GSONEEMpzsxSr8Y/WGYuIB33l29Tt9mNGUgSw/zjMYQjUVvQv+SY8dw62JV8d+3wK2YL2/r73gms6I8EE1JxX53KuAAY+x0p2v/W8ilCYI2Ijyzc8KIPwntmIFpibQjx+rkb+qdT
diff --git a/regress/misc/kexfuzz/Makefile b/regress/misc/kexfuzz/Makefile
deleted file mode 100644
index ede5e2fb4..000000000
--- a/regress/misc/kexfuzz/Makefile
+++ /dev/null
@@ -1,101 +0,0 @@
-# $OpenBSD: Makefile,v 1.8 2020/04/03 04:07:48 djm Exp $
-
-.include <bsd.own.mk>
-.include <bsd.obj.mk>
-
-# XXX detect from ssh binary?
-SSH1?= no
-OPENSSL?= yes
-
-PROG= kexfuzz
-SRCS= kexfuzz.c
-
-SSHREL=../../../../../usr.bin/ssh
-.PATH: ${.CURDIR}/${SSHREL}
-# From usr.bin/ssh
-SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
-SRCS+=atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c ssh-dss.c
-SRCS+=ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c
-SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c
-SRCS+=addrmatch.c bitmap.c packet.c dispatch.c canohost.c ssh_api.c
-SRCS+=compat.c ed25519.c hash.c ge25519.c fe25519.c sc25519.c verify.c
-SRCS+=cipher-chachapoly.c chacha.c poly1305.c utf8.c
-SRCS+=sshbuf-io.c ssh-ecdsa-sk.c ssh-ed25519-sk.c msg.c ssh-sk-client.c
-
-SRCS+= kex.c
-SRCS+= dh.c
-SRCS+= kexdh.c
-SRCS+= kexecdh.c
-SRCS+= kexgex.c
-SRCS+= kexgexc.c
-SRCS+= kexgexs.c
-SRCS+= kexc25519.c
-SRCS+= smult_curve25519_ref.c
-SRCS+= kexgen.c
-SRCS+= kexsntrup4591761x25519.c
-SRCS+= sntrup4591761.c
-
-SRCS+=digest-openssl.c
-#SRCS+=digest-libc.c
-
-NOMAN= 1
-
-.if (${OPENSSL:L} == "yes")
-CFLAGS+= -DWITH_OPENSSL
-.else
-# SSH v.1 requires OpenSSL.
-SSH1= no
-.endif
-
-.if (${SSH1:L} == "yes")
-CFLAGS+= -DWITH_SSH1
-.endif
-
-LDADD+= -lfido2 -lcbor -lusbhid
-DPADD+= ${LIBFIDO2} ${LIBCBOR} ${LIBUSBHID}
-
-# enable warnings
-WARNINGS=Yes
-
-DEBUG=-g
-CFLAGS+= -fstack-protector-all
-CDIAGFLAGS= -Wall
-CDIAGFLAGS+= -Wextra
-CDIAGFLAGS+= -Werror
-CDIAGFLAGS+= -Wchar-subscripts
-CDIAGFLAGS+= -Wcomment
-CDIAGFLAGS+= -Wformat
-CDIAGFLAGS+= -Wformat-security
-CDIAGFLAGS+= -Wimplicit
-CDIAGFLAGS+= -Winline
-CDIAGFLAGS+= -Wmissing-declarations
-CDIAGFLAGS+= -Wmissing-prototypes
-CDIAGFLAGS+= -Wparentheses
-CDIAGFLAGS+= -Wpointer-arith
-CDIAGFLAGS+= -Wreturn-type
-CDIAGFLAGS+= -Wshadow
-CDIAGFLAGS+= -Wsign-compare
-CDIAGFLAGS+= -Wstrict-aliasing
-CDIAGFLAGS+= -Wstrict-prototypes
-CDIAGFLAGS+= -Wswitch
-CDIAGFLAGS+= -Wtrigraphs
-CDIAGFLAGS+= -Wuninitialized
-CDIAGFLAGS+= -Wunused
-CDIAGFLAGS+= -Wno-unused-parameter
-.if ${COMPILER_VERSION:L} != "gcc3"
-CDIAGFLAGS+= -Wold-style-definition
-.endif
-
-
-CFLAGS+=-I${.CURDIR}/${SSHREL}
-
-LDADD+= -lutil -lz
-DPADD+= ${LIBUTIL} ${LIBZ}
-
-.if (${OPENSSL:L} == "yes")
-LDADD+= -lcrypto
-DPADD+= ${LIBCRYPTO}
-.endif
-
-.include <bsd.prog.mk>
-
diff --git a/regress/misc/kexfuzz/README b/regress/misc/kexfuzz/README
deleted file mode 100644
index 504c26f3b..000000000
--- a/regress/misc/kexfuzz/README
+++ /dev/null
@@ -1,34 +0,0 @@
-This is a harness to help with fuzzing KEX.
-
-To use it, you first set it to count packets in each direction:
-
-./kexfuzz -K diffie-hellman-group1-sha1 -k host_ed25519_key -c
-S2C: 29
-C2S: 31
-
-Then get it to record a particular packet (in this case the 4th
-packet from client->server):
-
-./kexfuzz -K diffie-hellman-group1-sha1 -k host_ed25519_key \
- -d -D C2S -i 3 -f packet_3
-
-Fuzz the packet somehow:
-
-dd if=/dev/urandom of=packet_3 bs=32 count=1 # Just for example
-
-Then re-run the key exchange substituting the modified packet in
-its original sequence:
-
-./kexfuzz -K diffie-hellman-group1-sha1 -k host_ed25519_key \
- -r -D C2S -i 3 -f packet_3
-
-A comprehensive KEX fuzz run would fuzz every packet in both
-directions for each key exchange type and every hostkey type.
-This will take some time.
-
-Limitations: kexfuzz can't change the ordering of packets at
-present. It is limited to replacing individual packets with
-fuzzed variants with the same type. It really should allow
-insertion, deletion on replacement of packets too.
-
-$OpenBSD: README,v 1.3 2017/10/20 02:13:41 djm Exp $
diff --git a/regress/misc/kexfuzz/kexfuzz.c b/regress/misc/kexfuzz/kexfuzz.c
deleted file mode 100644
index 56697c918..000000000
--- a/regress/misc/kexfuzz/kexfuzz.c
+++ /dev/null
@@ -1,453 +0,0 @@
-/* $OpenBSD: kexfuzz.c,v 1.6 2020/01/26 00:09:50 djm Exp $ */
-/*
- * Fuzz harness for KEX code
- *
- * Placed in the public domain
- */
-
-#include "includes.h"
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <stdio.h>
-#ifdef HAVE_STDINT_H
-# include <stdint.h>
-#endif
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#ifdef HAVE_ERR_H
-# include <err.h>
-#endif
-
-#include "ssherr.h"
-#include "ssh_api.h"
-#include "sshbuf.h"
-#include "packet.h"
-#include "myproposal.h"
-#include "authfile.h"
-#include "log.h"
-
-void kex_tests(void);
-static int do_debug = 0;
-
-enum direction { S2C, C2S };
-
-struct hook_ctx {
- struct ssh *client, *server, *server2;
- int *c2s, *s2c;
- int trigger_direction, packet_index;
- const char *dump_path;
- struct sshbuf *replace_data;
-};
-
-static int
-packet_hook(struct ssh *ssh, struct sshbuf *packet, u_char *typep, void *_ctx)
-{
- struct hook_ctx *ctx = (struct hook_ctx *)_ctx;
- int mydirection = ssh == ctx->client ? S2C : C2S;
- int *packet_count = mydirection == S2C ? ctx->s2c : ctx->c2s;
- FILE *dumpfile;
- int r;
-
- if (do_debug) {
- printf("%s packet %d type %u:\n",
- mydirection == S2C ? "s2c" : "c2s",
- *packet_count, *typep);
- sshbuf_dump(packet, stdout);
- }
- if (mydirection == ctx->trigger_direction &&
- ctx->packet_index == *packet_count) {
- if (ctx->replace_data != NULL) {
- sshbuf_reset(packet);
- /* Type is first byte of packet */
- if ((r = sshbuf_get_u8(ctx->replace_data,
- typep)) != 0 ||
- (r = sshbuf_putb(packet, ctx->replace_data)) != 0)
- return r;
- if (do_debug) {
- printf("***** replaced packet type %u\n",
- *typep);
- sshbuf_dump(packet, stdout);
- }
- } else if (ctx->dump_path != NULL) {
- if ((dumpfile = fopen(ctx->dump_path, "w+")) == NULL)
- err(1, "fopen %s", ctx->dump_path);
- /* Write { type, packet } */
- if (fwrite(typep, 1, 1, dumpfile) != 1)
- err(1, "fwrite type %s", ctx->dump_path);
- if (sshbuf_len(packet) != 0 &&
- fwrite(sshbuf_ptr(packet), sshbuf_len(packet),
- 1, dumpfile) != 1)
- err(1, "fwrite body %s", ctx->dump_path);
- if (do_debug) {
- printf("***** dumped packet type %u len %zu\n",
- *typep, sshbuf_len(packet));
- }
- fclose(dumpfile);
- /* No point in continuing */
- exit(0);
- }
- }
- (*packet_count)++;
- return 0;
-}
-
-static int
-do_send_and_receive(struct ssh *from, struct ssh *to)
-{
- u_char type;
- size_t len;
- const u_char *buf;
- int r;
-
- for (;;) {
- if ((r = ssh_packet_next(from, &type)) != 0) {
- fprintf(stderr, "ssh_packet_next: %s\n", ssh_err(r));
- return r;
- }
-
- if (type != 0)
- return 0;
- buf = ssh_output_ptr(from, &len);
- if (len == 0)
- return 0;
- if ((r = ssh_input_append(to, buf, len)) != 0) {
- debug("ssh_input_append: %s", ssh_err(r));
- return r;
- }
- if ((r = ssh_output_consume(from, len)) != 0) {
- debug("ssh_output_consume: %s", ssh_err(r));
- return r;
- }
- }
-}
-
-/* Minimal test_helper.c scaffholding to make this standalone */
-const char *in_test = NULL;
-#define TEST_START(a) \
- do { \
- in_test = (a); \
- if (do_debug) \
- fprintf(stderr, "test %s starting\n", in_test); \
- } while (0)
-#define TEST_DONE() \
- do { \
- if (do_debug) \
- fprintf(stderr, "test %s done\n", \
- in_test ? in_test : "???"); \
- in_test = NULL; \
- } while(0)
-#define ASSERT_INT_EQ(a, b) \
- do { \
- if ((int)(a) != (int)(b)) { \
- fprintf(stderr, "%s %s:%d " \
- "%s (%d) != expected %s (%d)\n", \
- in_test ? in_test : "(none)", \
- __func__, __LINE__, #a, (int)(a), #b, (int)(b)); \
- exit(2); \
- } \
- } while (0)
-#define ASSERT_INT_GE(a, b) \
- do { \
- if ((int)(a) < (int)(b)) { \
- fprintf(stderr, "%s %s:%d " \
- "%s (%d) < expected %s (%d)\n", \
- in_test ? in_test : "(none)", \
- __func__, __LINE__, #a, (int)(a), #b, (int)(b)); \
- exit(2); \
- } \
- } while (0)
-#define ASSERT_PTR_NE(a, b) \
- do { \
- if ((a) == (b)) { \
- fprintf(stderr, "%s %s:%d " \
- "%s (%p) != expected %s (%p)\n", \
- in_test ? in_test : "(none)", \
- __func__, __LINE__, #a, (a), #b, (b)); \
- exit(2); \
- } \
- } while (0)
-
-
-static void
-run_kex(struct ssh *client, struct ssh *server)
-{
- int r = 0;
-
- while (!server->kex->done || !client->kex->done) {
- if ((r = do_send_and_receive(server, client)) != 0) {
- debug("do_send_and_receive S2C: %s", ssh_err(r));
- break;
- }
- if ((r = do_send_and_receive(client, server)) != 0) {
- debug("do_send_and_receive C2S: %s", ssh_err(r));
- break;
- }
- }
- if (do_debug)
- printf("done: %s\n", ssh_err(r));
- ASSERT_INT_EQ(r, 0);
- ASSERT_INT_EQ(server->kex->done, 1);
- ASSERT_INT_EQ(client->kex->done, 1);
-}
-
-static void
-do_kex_with_key(const char *kex, struct sshkey *prvkey, int *c2s, int *s2c,
- int direction, int packet_index,
- const char *dump_path, struct sshbuf *replace_data)
-{
- struct ssh *client = NULL, *server = NULL, *server2 = NULL;
- struct sshkey *pubkey = NULL;
- struct sshbuf *state;
- struct kex_params kex_params;
- char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
- char *keyname = NULL;
- struct hook_ctx hook_ctx;
-
- TEST_START("sshkey_from_private");
- ASSERT_INT_EQ(sshkey_from_private(prvkey, &pubkey), 0);
- TEST_DONE();
-
- TEST_START("ssh_init");
- memcpy(kex_params.proposal, myproposal, sizeof(myproposal));
- if (kex != NULL)
- kex_params.proposal[PROPOSAL_KEX_ALGS] = strdup(kex);
- keyname = strdup(sshkey_ssh_name(prvkey));
- ASSERT_PTR_NE(keyname, NULL);
- kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname;
- ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0);
- ASSERT_INT_EQ(ssh_init(&server, 1, &kex_params), 0);
- ASSERT_INT_EQ(ssh_init(&server2, 1, NULL), 0);
- ASSERT_PTR_NE(client, NULL);
- ASSERT_PTR_NE(server, NULL);
- ASSERT_PTR_NE(server2, NULL);
- TEST_DONE();
-
- hook_ctx.c2s = c2s;
- hook_ctx.s2c = s2c;
- hook_ctx.trigger_direction = direction;
- hook_ctx.packet_index = packet_index;
- hook_ctx.dump_path = dump_path;
- hook_ctx.replace_data = replace_data;
- hook_ctx.client = client;
- hook_ctx.server = server;
- hook_ctx.server2 = server2;
- ssh_packet_set_input_hook(client, packet_hook, &hook_ctx);
- ssh_packet_set_input_hook(server, packet_hook, &hook_ctx);
- ssh_packet_set_input_hook(server2, packet_hook, &hook_ctx);
-
- TEST_START("ssh_add_hostkey");
- ASSERT_INT_EQ(ssh_add_hostkey(server, prvkey), 0);
- ASSERT_INT_EQ(ssh_add_hostkey(client, pubkey), 0);
- TEST_DONE();
-
- TEST_START("kex");
- run_kex(client, server);
- TEST_DONE();
-
- TEST_START("rekeying client");
- ASSERT_INT_EQ(kex_send_kexinit(client), 0);
- run_kex(client, server);
- TEST_DONE();
-
- TEST_START("rekeying server");
- ASSERT_INT_EQ(kex_send_kexinit(server), 0);
- run_kex(client, server);
- TEST_DONE();
-
- TEST_START("ssh_packet_get_state");
- state = sshbuf_new();
- ASSERT_PTR_NE(state, NULL);
- ASSERT_INT_EQ(ssh_packet_get_state(server, state), 0);
- ASSERT_INT_GE(sshbuf_len(state), 1);
- TEST_DONE();
-
- TEST_START("ssh_packet_set_state");
- ASSERT_INT_EQ(ssh_add_hostkey(server2, prvkey), 0);
- kex_free(server2->kex); /* XXX or should ssh_packet_set_state()? */
- ASSERT_INT_EQ(ssh_packet_set_state(server2, state), 0);
- ASSERT_INT_EQ(sshbuf_len(state), 0);
- sshbuf_free(state);
- ASSERT_PTR_NE(server2->kex, NULL);
- /* XXX we need to set the callbacks */
-#ifdef WITH_OPENSSL
- server2->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server;
- server2->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_server;
- server2->kex->kex[KEX_DH_GRP14_SHA256] = kex_gen_server;
- server2->kex->kex[KEX_DH_GRP16_SHA512] = kex_gen_server;
- server2->kex->kex[KEX_DH_GRP18_SHA512] = kex_gen_server;
- server2->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
- server2->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
-# ifdef OPENSSL_HAS_ECC
- server2->kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
-# endif
-#endif
- server2->kex->kex[KEX_C25519_SHA256] = kex_gen_server;
- server2->kex->load_host_public_key = server->kex->load_host_public_key;
- server2->kex->load_host_private_key = server->kex->load_host_private_key;
- server2->kex->sign = server->kex->sign;
- TEST_DONE();
-
- TEST_START("rekeying server2");
- ASSERT_INT_EQ(kex_send_kexinit(server2), 0);
- run_kex(client, server2);
- ASSERT_INT_EQ(kex_send_kexinit(client), 0);
- run_kex(client, server2);
- TEST_DONE();
-
- TEST_START("cleanup");
- sshkey_free(pubkey);
- ssh_free(client);
- ssh_free(server);
- ssh_free(server2);
- free(keyname);
- TEST_DONE();
-}
-
-static void
-usage(void)
-{
- fprintf(stderr,
- "Usage: kexfuzz [-hcdrv] [-D direction] [-f data_file]\n"
- " [-K kex_alg] [-k private_key] [-i packet_index]\n"
- "\n"
- "Options:\n"
- " -h Display this help\n"
- " -c Count packets sent during KEX\n"
- " -d Dump mode: record KEX packet to data file\n"
- " -r Replace mode: replace packet with data file\n"
- " -v Turn on verbose logging\n"
- " -D S2C|C2S Packet direction for replacement or dump\n"
- " -f data_file Path to data file for replacement or dump\n"
- " -K kex_alg Name of KEX algorithm to test (see below)\n"
- " -k private_key Path to private key file\n"
- " -i packet_index Index of packet to replace or dump (from 0)\n"
- "\n"
- "Available KEX algorithms: %s\n", kex_alg_list(' '));
-}
-
-static void
-badusage(const char *bad)
-{
- fprintf(stderr, "Invalid options\n");
- fprintf(stderr, "%s\n", bad);
- usage();
- exit(1);
-}
-
-int
-main(int argc, char **argv)
-{
- int ch, fd, r;
- int count_flag = 0, dump_flag = 0, replace_flag = 0;
- int packet_index = -1, direction = -1;
- int s2c = 0, c2s = 0; /* packet counts */
- const char *kex = NULL, *kpath = NULL, *data_path = NULL;
- struct sshkey *key = NULL;
- struct sshbuf *replace_data = NULL;
-
- setvbuf(stdout, NULL, _IONBF, 0);
- while ((ch = getopt(argc, argv, "hcdrvD:f:K:k:i:")) != -1) {
- switch (ch) {
- case 'h':
- usage();
- return 0;
- case 'c':
- count_flag = 1;
- break;
- case 'd':
- dump_flag = 1;
- break;
- case 'r':
- replace_flag = 1;
- break;
- case 'v':
- do_debug = 1;
- break;
-
- case 'D':
- if (strcasecmp(optarg, "s2c") == 0)
- direction = S2C;
- else if (strcasecmp(optarg, "c2s") == 0)
- direction = C2S;
- else
- badusage("Invalid direction (-D)");
- break;
- case 'f':
- data_path = optarg;
- break;
- case 'K':
- kex = optarg;
- break;
- case 'k':
- kpath = optarg;
- break;
- case 'i':
- packet_index = atoi(optarg);
- if (packet_index < 0)
- badusage("Invalid packet index");
- break;
- default:
- badusage("unsupported flag");
- }
- }
- argc -= optind;
- argv += optind;
-
- log_init(argv[0], do_debug ? SYSLOG_LEVEL_DEBUG3 : SYSLOG_LEVEL_INFO,
- SYSLOG_FACILITY_USER, 1);
-
- /* Must select a single mode */
- if ((count_flag + dump_flag + replace_flag) != 1)
- badusage("Must select one mode: -c, -d or -r");
- /* KEX type is mandatory */
- if (kex == NULL || !kex_names_valid(kex) || strchr(kex, ',') != NULL)
- badusage("Missing or invalid kex type (-K flag)");
- /* Valid key is mandatory */
- if (kpath == NULL)
- badusage("Missing private key (-k flag)");
- if ((fd = open(kpath, O_RDONLY)) == -1)
- err(1, "open %s", kpath);
- if ((r = sshkey_load_private_type_fd(fd, KEY_UNSPEC, NULL,
- &key, NULL)) != 0)
- errx(1, "Unable to load key %s: %s", kpath, ssh_err(r));
- close(fd);
- /* XXX check that it is a private key */
- /* XXX support certificates */
- if (key == NULL || key->type == KEY_UNSPEC)
- badusage("Invalid key file (-k flag)");
-
- /* Replace (fuzz) mode */
- if (replace_flag) {
- if (packet_index == -1 || direction == -1 || data_path == NULL)
- badusage("Replace (-r) mode must specify direction "
- "(-D) packet index (-i) and data path (-f)");
- if ((r = sshbuf_load_file(data_path, &replace_data)) != 0)
- errx(1, "read %s: %s", data_path, ssh_err(r));
- }
-
- /* Dump mode */
- if (dump_flag) {
- if (packet_index == -1 || direction == -1 || data_path == NULL)
- badusage("Dump (-d) mode must specify direction "
- "(-D), packet index (-i) and data path (-f)");
- }
-
- /* Count mode needs no further flags */
-
- do_kex_with_key(kex, key, &c2s, &s2c,
- direction, packet_index,
- dump_flag ? data_path : NULL,
- replace_flag ? replace_data : NULL);
- sshkey_free(key);
- sshbuf_free(replace_data);
-
- if (count_flag) {
- printf("S2C: %d\n", s2c);
- printf("C2S: %d\n", c2s);
- }
-
- return 0;
-}
diff --git a/regress/misc/sk-dummy/fatal.c b/regress/misc/sk-dummy/fatal.c
index 7cdc74b97..c6e4b5d6f 100644
--- a/regress/misc/sk-dummy/fatal.c
+++ b/regress/misc/sk-dummy/fatal.c
@@ -1,20 +1,27 @@
/* public domain */
+#include "includes.h"
+
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
-void fatal(char *fmt, ...);
+#include "log.h"
void
-fatal(char *fmt, ...)
+sshfatal(const char *file, const char *func, int line, int showfunc,
+ LogLevel level, const char *suffix, const char *fmt, ...)
{
va_list ap;
+ if (showfunc)
+ fprintf(stderr, "%s: ", func);
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
+ if (suffix != NULL)
+ fprintf(stderr, ": %s", suffix);
fputc('\n', stderr);
_exit(1);
}
diff --git a/regress/misc/sk-dummy/sk-dummy.c b/regress/misc/sk-dummy/sk-dummy.c
index f3acb2fb7..4003362d7 100644
--- a/regress/misc/sk-dummy/sk-dummy.c
+++ b/regress/misc/sk-dummy/sk-dummy.c
@@ -47,10 +47,17 @@
} while (0)
#endif
-#if SSH_SK_VERSION_MAJOR != 0x00050000
+#if SSH_SK_VERSION_MAJOR != 0x00070000
# error SK API has changed, sk-dummy.c needs an update
#endif
+#ifdef SK_DUMMY_INTEGRATE
+# define sk_api_version ssh_sk_api_version
+# define sk_enroll ssh_sk_enroll
+# define sk_sign ssh_sk_sign
+# define sk_load_resident_keys ssh_sk_load_resident_keys
+#endif /* !SK_STANDALONE */
+
static void skdebug(const char *func, const char *fmt, ...)
__attribute__((__format__ (printf, 2, 3)));
diff --git a/regress/multiplex.sh b/regress/multiplex.sh
index 817ddbfa8..4744fa3d9 100644
--- a/regress/multiplex.sh
+++ b/regress/multiplex.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: multiplex.sh,v 1.32 2020/01/25 02:57:53 dtucker Exp $
+# $OpenBSD: multiplex.sh,v 1.33 2020/06/24 15:16:23 markus Exp $
# Placed in the Public Domain.
make_tmpdir
@@ -97,22 +97,24 @@ kill $netcat_pid 2>/dev/null
rm -f ${COPY} $OBJ/unix-[123].fwd
for s in 0 1 4 5 44; do
- trace "exit status $s over multiplexed connection"
- verbose "test $tid: status $s"
- ${SSH} -F $OBJ/ssh_config -S $CTL otherhost exit $s
+ for mode in "" "-Oproxy"; do
+ trace "exit status $s over multiplexed connection ($mode)"
+ verbose "test $tid: status $s ($mode)"
+ ${SSH} -F $OBJ/ssh_config -S $CTL $mode otherhost exit $s
r=$?
if [ $r -ne $s ]; then
fail "exit code mismatch: $r != $s"
fi
# same with early close of stdout/err
- trace "exit status $s with early close over multiplexed connection"
- ${SSH} -F $OBJ/ssh_config -S $CTL -n otherhost \
+ trace "exit status $s with early close over multiplexed connection ($mode)"
+ ${SSH} -F $OBJ/ssh_config -S $CTL -n $mode otherhost \
exec sh -c \'"sleep 2; exec > /dev/null 2>&1; sleep 3; exit $s"\'
r=$?
if [ $r -ne $s ]; then
fail "exit code (with sleep) mismatch: $r != $s"
fi
+ done
done
verbose "test $tid: cmd check"
diff --git a/regress/multipubkey.sh b/regress/multipubkey.sh
index 9b2273353..8cdda1a9a 100644
--- a/regress/multipubkey.sh
+++ b/regress/multipubkey.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: multipubkey.sh,v 1.3 2019/12/11 18:47:14 djm Exp $
+# $OpenBSD: multipubkey.sh,v 1.4 2021/06/07 01:16:34 djm Exp $
# Placed in the Public Domain.
tid="multiple pubkey"
@@ -31,27 +31,35 @@ grep -v IdentityFile $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy
opts="-oProtocol=2 -F $OBJ/ssh_proxy -oIdentitiesOnly=yes"
opts="$opts -i $OBJ/cert_user_key1 -i $OBJ/user_key1 -i $OBJ/user_key2"
-for privsep in yes ; do
+for match in no yes ; do
(
- grep -v "Protocol" $OBJ/sshd_proxy.orig
+ cat $OBJ/sshd_proxy.orig
echo "Protocol 2"
- echo "UsePrivilegeSeparation $privsep"
- echo "AuthenticationMethods publickey,publickey"
echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
echo "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
) > $OBJ/sshd_proxy
+ if test "$match" = "yes" ; then
+ echo "AuthenticationMethods none" >> $OBJ/sshd_proxy
+ echo "PubkeyAuthentication no" >> $OBJ/sshd_proxy
+ echo "Match all" >> $OBJ/sshd_proxy
+ echo "PubkeyAuthentication yes" >> $OBJ/sshd_proxy
+ fi
+ echo "AuthenticationMethods publickey,publickey" >> $OBJ/sshd_proxy
# Single key should fail.
+ trace "match $match single key"
rm -f $OBJ/authorized_principals_$USER
cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER
${SSH} $opts proxy true && fail "ssh succeeded with key"
# Single key with same-public cert should fail.
+ trace "match $match pubkey + identical cert"
echo mekmitasdigoat > $OBJ/authorized_principals_$USER
cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER
${SSH} $opts proxy true && fail "ssh succeeded with key+cert"
# Multiple plain keys should succeed.
+ trace "match $match multiple public"
rm -f $OBJ/authorized_principals_$USER
cat $OBJ/user_key1.pub $OBJ/user_key2.pub > \
$OBJ/authorized_keys_$USER
@@ -59,6 +67,7 @@ for privsep in yes ; do
# Cert and different key should succeed
# Key and different-public cert should succeed.
+ trace "match $match pubkey + different cert"
echo mekmitasdigoat > $OBJ/authorized_principals_$USER
cat $OBJ/user_key2.pub > $OBJ/authorized_keys_$USER
${SSH} $opts proxy true || fail "ssh failed with key/cert"
diff --git a/regress/netcat.c b/regress/netcat.c
index fe94dd908..20ec3f595 100644
--- a/regress/netcat.c
+++ b/regress/netcat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: netcat.c,v 1.126 2014/10/30 16:08:31 tedu Exp $ */
+/* $OpenBSD: netcat.c,v 1.131 2015/09/03 23:06:28 sobrado Exp $ */
/*
* Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
*
@@ -44,14 +44,15 @@
#include <netinet/ip.h>
#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
#include <netdb.h>
+#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <fcntl.h>
-#include <limits.h>
#include "atomicio.h"
#ifdef HAVE_POLL_H
@@ -68,6 +69,9 @@
# include <sys/byteorder.h>
#endif
+/* rename to avoid collision in libssh */
+#define timeout_connect netcat_timeout_connect
+
/* Telnet options from arpa/telnet.h */
#define IAC 255
#define DONT 254
@@ -133,7 +137,7 @@ int udptest(int);
int unix_bind(char *);
int unix_connect(char *);
int unix_listen(char *);
-void set_common_sockopts(int);
+void set_common_sockopts(int, int);
int map_tos(char *, int *);
void report_connect(const struct sockaddr *, socklen_t);
void usage(int);
@@ -162,6 +166,8 @@ main(int argc, char *argv[])
uport = NULL;
sv = NULL;
+ signal(SIGPIPE, SIG_IGN);
+
while ((ch = getopt(argc, argv,
"46DdFhI:i:klNnO:P:p:rSs:tT:UuV:vw:X:x:z")) != -1) {
switch (ch) {
@@ -648,7 +654,7 @@ remote_connect(const char *host, const char *port, struct addrinfo hints)
freeaddrinfo(ares);
}
- set_common_sockopts(s);
+ set_common_sockopts(s, res0->ai_family);
if (timeout_connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
break;
@@ -748,7 +754,7 @@ local_listen(char *host, char *port, struct addrinfo hints)
if (ret == -1)
err(1, "setsockopt SO_REUSEADDR");
#endif
- set_common_sockopts(s);
+ set_common_sockopts(s, res0->ai_family);
if (bind(s, (struct sockaddr *)res0->ai_addr,
res0->ai_addrlen) == 0)
@@ -1034,17 +1040,17 @@ fdpass(int nfd)
bzero(&pfd, sizeof(pfd));
pfd.fd = STDOUT_FILENO;
+ pfd.events = POLLOUT;
for (;;) {
r = sendmsg(STDOUT_FILENO, &msg, 0);
if (r == -1) {
if (errno == EAGAIN || errno == EINTR) {
- pfd.events = POLLOUT;
if (poll(&pfd, 1, -1) == -1)
err(1, "poll");
continue;
}
err(1, "sendmsg");
- } else if (r == -1)
+ } else if (r != 1)
errx(1, "sendmsg: unexpected return value %zd", r);
else
break;
@@ -1168,7 +1174,7 @@ udptest(int s)
}
void
-set_common_sockopts(int s)
+set_common_sockopts(int s, int af)
{
int x = 1;
@@ -1184,10 +1190,19 @@ set_common_sockopts(int s)
&x, sizeof(x)) == -1)
err(1, "setsockopt");
}
-#ifdef IP_TOS
+#if defined(IP_TOS) && defined(IPV6_TCLASS)
if (Tflag != -1) {
- if (setsockopt(s, IPPROTO_IP, IP_TOS,
- &Tflag, sizeof(Tflag)) == -1)
+ int proto, option;
+
+ if (af == AF_INET6) {
+ proto = IPPROTO_IPV6;
+ option = IPV6_TCLASS;
+ } else {
+ proto = IPPROTO_IP;
+ option = IP_TOS;
+ }
+
+ if (setsockopt(s, proto, option, &Tflag, sizeof(Tflag)) == -1)
err(1, "set IP ToS");
}
#endif
@@ -1321,7 +1336,7 @@ usage(int ret)
{
fprintf(stderr,
"usage: nc [-46DdFhklNnrStUuvz] [-I length] [-i interval] [-O length]\n"
- "\t [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n"
+ "\t [-P proxy_username] [-p source_port] [-s source] [-T toskeyword]\n"
"\t [-V rtable] [-w timeout] [-X proxy_protocol]\n"
"\t [-x proxy_address[:port]] [destination] [port]\n");
if (ret)
diff --git a/regress/percent.sh b/regress/percent.sh
index 2e891f693..7ed41845b 100644
--- a/regress/percent.sh
+++ b/regress/percent.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: percent.sh,v 1.6 2020/04/10 00:54:03 dtucker Exp $
+# $OpenBSD: percent.sh,v 1.13 2021/07/25 12:13:03 dtucker Exp $
# Placed in the Public Domain.
tid="percent expansions"
@@ -25,12 +25,21 @@ trial()
trace "test $opt=$arg $expect"
rm -f $OBJ/actual
+ got=""
case "$opt" in
localcommand)
${SSH} -F $OBJ/ssh_proxy -o $opt="echo '$arg' >$OBJ/actual" \
somehost true
got=`cat $OBJ/actual`
;;
+ userknownhostsfile)
+ # Move the userknownhosts file to what the expansion says,
+ # make sure ssh works then put it back.
+ mv "$OBJ/known_hosts" "$OBJ/$expect"
+ ${SSH} -F $OBJ/ssh_proxy -o $opt="$OBJ/$arg" somehost true && \
+ got="$expect"
+ mv "$OBJ/$expect" "$OBJ/known_hosts"
+ ;;
matchexec)
(cat $OBJ/ssh_proxy && \
echo "Match Exec \"echo '$arg' >$OBJ/actual\"") \
@@ -55,34 +64,56 @@ trial()
}
for i in matchexec localcommand remotecommand controlpath identityagent \
- forwardagent localforward remoteforward; do
- verbose $tid $i
- if [ "$i" = "localcommand" ]; then
- REMUSER=$USER
+ forwardagent localforward remoteforward userknownhostsfile; do
+ verbose $tid $i percent
+ case "$i" in
+ localcommand|userknownhostsfile)
+ # Any test that's going to actually make a connection needs
+ # to use the real username.
+ REMUSER=$USER ;;
+ *)
+ REMUSER=remuser ;;
+ esac
+ if [ "$i" = "$localcommand" ]; then
trial $i '%T' NONE
- else
- REMUSER=remuser
fi
# Matches implementation in readconf.c:ssh_connection_hash()
HASH=`printf "${HOSTNAME}127.0.0.1${PORT}$REMUSER" |
- openssl sha1 | cut -f2 -d' '`
+ $OPENSSL_BIN sha1 | cut -f2 -d' '`
trial $i '%%' '%'
trial $i '%C' $HASH
trial $i '%i' $USERID
trial $i '%h' 127.0.0.1
- trial $i '%d' $HOME
trial $i '%L' $HOST
trial $i '%l' $HOSTNAME
trial $i '%n' somehost
+ trial $i '%k' localhost-with-alias
trial $i '%p' $PORT
trial $i '%r' $REMUSER
trial $i '%u' $USER
- trial $i '%%/%C/%i/%h/%d/%L/%l/%n/%p/%r/%u' \
- "%/$HASH/$USERID/127.0.0.1/$HOME/$HOST/$HOSTNAME/somehost/$PORT/$REMUSER/$USER"
+ # We can't specify a full path outside the regress dir, so skip tests
+ # containing %d for UserKnownHostsFile
+ if [ "$i" != "userknownhostsfile" ]; then
+ trial $i '%d' $HOME
+ trial $i '%%/%C/%i/%h/%d/%L/%l/%n/%p/%r/%u' \
+ "%/$HASH/$USERID/127.0.0.1/$HOME/$HOST/$HOSTNAME/somehost/$PORT/$REMUSER/$USER"
+ fi
done
+# Subset of above since we don't expand shell-style variables on anything that
+# runs a command because the shell will expand those.
+for i in controlpath identityagent forwardagent localforward remoteforward \
+ userknownhostsfile; do
+ verbose $tid $i dollar
+ FOO=bar
+ export FOO
+ trial $i '${FOO}' $FOO
+done
+
+
# A subset of options support tilde expansion
for i in controlpath identityagent forwardagent; do
+ verbose $tid $i tilde
trial $i '~' $HOME/
trial $i '~/.ssh' $HOME/.ssh
done
diff --git a/regress/putty-ciphers.sh b/regress/putty-ciphers.sh
index 708c288d7..5b8e25a27 100644
--- a/regress/putty-ciphers.sh
+++ b/regress/putty-ciphers.sh
@@ -1,11 +1,17 @@
-# $OpenBSD: putty-ciphers.sh,v 1.7 2020/01/23 03:35:07 dtucker Exp $
+# $OpenBSD: putty-ciphers.sh,v 1.11 2021/09/01 03:16:06 dtucker Exp $
# Placed in the Public Domain.
tid="putty ciphers"
if test "x$REGRESS_INTEROP_PUTTY" != "xyes" ; then
- echo "putty interop tests not enabled"
- exit 0
+ skip "putty interop tests not enabled"
+fi
+
+# Re-enable ssh-rsa on older PuTTY versions.
+oldver="`${PLINK} --version | awk '/plink: Release/{if ($3<0.76)print "yes"}'`"
+if [ "x$oldver" = "xyes" ]; then
+ echo "HostKeyAlgorithms +ssh-rsa" >> ${OBJ}/sshd_proxy
+ echo "PubkeyAcceptedKeyTypes +ssh-rsa" >> ${OBJ}/sshd_proxy
fi
for c in aes 3des aes128-ctr aes192-ctr aes256-ctr chacha20 ; do
diff --git a/regress/putty-kex.sh b/regress/putty-kex.sh
index 686d0e1af..c75802a06 100644
--- a/regress/putty-kex.sh
+++ b/regress/putty-kex.sh
@@ -1,11 +1,17 @@
-# $OpenBSD: putty-kex.sh,v 1.5 2020/01/23 03:24:38 dtucker Exp $
+# $OpenBSD: putty-kex.sh,v 1.9 2021/09/01 03:16:06 dtucker Exp $
# Placed in the Public Domain.
tid="putty KEX"
if test "x$REGRESS_INTEROP_PUTTY" != "xyes" ; then
- echo "putty interop tests not enabled"
- exit 0
+ skip "putty interop tests not enabled"
+fi
+
+# Re-enable ssh-rsa on older PuTTY versions.
+oldver="`${PLINK} --version | awk '/plink: Release/{if ($3<0.76)print "yes"}'`"
+if [ "x$oldver" = "xyes" ]; then
+ echo "HostKeyAlgorithms +ssh-rsa" >> ${OBJ}/sshd_proxy
+ echo "PubkeyAcceptedKeyTypes +ssh-rsa" >> ${OBJ}/sshd_proxy
fi
for k in dh-gex-sha1 dh-group1-sha1 dh-group14-sha1 ecdh ; do
diff --git a/regress/putty-transfer.sh b/regress/putty-transfer.sh
index 14b41022f..a6864f951 100644
--- a/regress/putty-transfer.sh
+++ b/regress/putty-transfer.sh
@@ -1,11 +1,17 @@
-# $OpenBSD: putty-transfer.sh,v 1.7 2020/01/23 11:19:12 dtucker Exp $
+# $OpenBSD: putty-transfer.sh,v 1.11 2021/09/01 03:16:06 dtucker Exp $
# Placed in the Public Domain.
tid="putty transfer data"
if test "x$REGRESS_INTEROP_PUTTY" != "xyes" ; then
- echo "putty interop tests not enabled"
- exit 0
+ skip "putty interop tests not enabled"
+fi
+
+# Re-enable ssh-rsa on older PuTTY versions.
+oldver="`${PLINK} --version | awk '/plink: Release/{if ($3<0.76)print "yes"}'`"
+if [ "x$oldver" = "xyes" ]; then
+ echo "HostKeyAlgorithms +ssh-rsa" >> ${OBJ}/sshd_proxy
+ echo "PubkeyAcceptedKeyTypes +ssh-rsa" >> ${OBJ}/sshd_proxy
fi
if [ "`${SSH} -Q compression`" = "none" ]; then
diff --git a/regress/reconfigure.sh b/regress/reconfigure.sh
index dd15eddb2..d5b4e9808 100644
--- a/regress/reconfigure.sh
+++ b/regress/reconfigure.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: reconfigure.sh,v 1.6 2017/04/30 23:34:55 djm Exp $
+# $OpenBSD: reconfigure.sh,v 1.9 2021/06/10 09:46:28 dtucker Exp $
# Placed in the Public Domain.
tid="simple connect after reconfigure"
@@ -41,3 +41,25 @@ ${SSH} -F $OBJ/ssh_config somehost true
if [ $? -ne 0 ]; then
fail "ssh connect with failed after reconfigure"
fi
+
+trace "reconfigure with active clients"
+${SSH} -F $OBJ/ssh_config somehost sleep 10 # authenticated client
+${NC} -d 127.0.0.1 $PORT >/dev/null & # unauthenticated client
+PID=`$SUDO cat $PIDFILE`
+rm -f $PIDFILE
+$SUDO kill -HUP $PID
+
+trace "wait for sshd to restart"
+i=0;
+while [ ! -f $PIDFILE -a $i -lt 10 ]; do
+ i=`expr $i + 1`
+ sleep $i
+done
+
+test -f $PIDFILE || fatal "sshd did not restart"
+
+trace "connect after restart with active clients"
+${SSH} -F $OBJ/ssh_config somehost true
+if [ $? -ne 0 ]; then
+ fail "ssh connect with failed after reconfigure"
+fi
diff --git a/regress/rekey.sh b/regress/rekey.sh
index fd6a02cc7..61723cd86 100644
--- a/regress/rekey.sh
+++ b/regress/rekey.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: rekey.sh,v 1.18 2018/04/10 00:14:10 djm Exp $
+# $OpenBSD: rekey.sh,v 1.19 2021/07/19 05:08:54 dtucker Exp $
# Placed in the Public Domain.
tid="rekey"
@@ -71,7 +71,7 @@ for s in 5 10; do
verbose "client rekeylimit default ${s}"
rm -f ${COPY} ${LOG}
${SSH} < ${DATA} -oCompression=no -oRekeyLimit="default $s" -F \
- $OBJ/ssh_proxy somehost "cat >${COPY};sleep $s;sleep 3"
+ $OBJ/ssh_proxy somehost "cat >${COPY};sleep $s;sleep 10"
if [ $? -ne 0 ]; then
fail "ssh failed"
fi
@@ -88,7 +88,7 @@ for s in 5 10; do
verbose "client rekeylimit default ${s} no data"
rm -f ${COPY} ${LOG}
${SSH} -oCompression=no -oRekeyLimit="default $s" -F \
- $OBJ/ssh_proxy somehost "sleep $s;sleep 3"
+ $OBJ/ssh_proxy somehost "sleep $s;sleep 10"
if [ $? -ne 0 ]; then
fail "ssh failed"
fi
@@ -124,7 +124,7 @@ for s in 5 10; do
cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
echo "rekeylimit default ${s}" >>$OBJ/sshd_proxy
rm -f ${COPY} ${LOG}
- ${SSH} -oCompression=no -F $OBJ/ssh_proxy somehost "sleep $s;sleep 3"
+ ${SSH} -oCompression=no -F $OBJ/ssh_proxy somehost "sleep $s;sleep 10"
if [ $? -ne 0 ]; then
fail "ssh failed"
fi
diff --git a/regress/scp-uri.sh b/regress/scp-uri.sh
index c03d8bbe0..20ac3c89e 100644
--- a/regress/scp-uri.sh
+++ b/regress/scp-uri.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: scp-uri.sh,v 1.2 2017/12/11 11:41:56 dtucker Exp $
+# $OpenBSD: scp-uri.sh,v 1.4 2021/08/10 03:35:45 djm Exp $
# Placed in the Public Domain.
tid="scp-uri"
@@ -12,7 +12,6 @@ DIR2=${COPY}.dd2
SRC=`dirname ${SCRIPT}`
cp ${SRC}/scp-ssh-wrapper.sh ${OBJ}/scp-ssh-wrapper.scp
chmod 755 ${OBJ}/scp-ssh-wrapper.scp
-scpopts="-q -S ${OBJ}/scp-ssh-wrapper.scp"
export SCP # used in scp-ssh-wrapper.scp
scpclean() {
@@ -24,47 +23,55 @@ scpclean() {
cp $OBJ/ssh_config $OBJ/ssh_config.orig
egrep -v '^ +(Port|User) +.*$' $OBJ/ssh_config.orig > $OBJ/ssh_config
-verbose "$tid: simple copy local file to remote file"
-scpclean
-$SCP $scpopts ${DATA} "scp://${USER}@somehost:${PORT}/${COPY}" || fail "copy failed"
-cmp ${DATA} ${COPY} || fail "corrupted copy"
+for mode in scp sftp ; do
+ tag="$tid: $mode mode"
+ if test $mode = scp ; then
+ scpopts="-O -q -S ${OBJ}/scp-ssh-wrapper.scp"
+ else
+ scpopts="-s -D ${SFTPSERVER}"
+ fi
+ verbose "$tag: simple copy local file to remote file"
+ scpclean
+ $SCP $scpopts ${DATA} "scp://${USER}@somehost:${PORT}/${COPY}" || fail "copy failed"
+ cmp ${DATA} ${COPY} || fail "corrupted copy"
-verbose "$tid: simple copy remote file to local file"
-scpclean
-$SCP $scpopts "scp://${USER}@somehost:${PORT}/${DATA}" ${COPY} || fail "copy failed"
-cmp ${DATA} ${COPY} || fail "corrupted copy"
+ verbose "$tag: simple copy remote file to local file"
+ scpclean
+ $SCP $scpopts "scp://${USER}@somehost:${PORT}/${DATA}" ${COPY} || fail "copy failed"
+ cmp ${DATA} ${COPY} || fail "corrupted copy"
-verbose "$tid: simple copy local file to remote dir"
-scpclean
-cp ${DATA} ${COPY}
-$SCP $scpopts ${COPY} "scp://${USER}@somehost:${PORT}/${DIR}" || fail "copy failed"
-cmp ${COPY} ${DIR}/copy || fail "corrupted copy"
+ verbose "$tag: simple copy local file to remote dir"
+ scpclean
+ cp ${DATA} ${COPY}
+ $SCP $scpopts ${COPY} "scp://${USER}@somehost:${PORT}/${DIR}" || fail "copy failed"
+ cmp ${COPY} ${DIR}/copy || fail "corrupted copy"
-verbose "$tid: simple copy remote file to local dir"
-scpclean
-cp ${DATA} ${COPY}
-$SCP $scpopts "scp://${USER}@somehost:${PORT}/${COPY}" ${DIR} || fail "copy failed"
-cmp ${COPY} ${DIR}/copy || fail "corrupted copy"
+ verbose "$tag: simple copy remote file to local dir"
+ scpclean
+ cp ${DATA} ${COPY}
+ $SCP $scpopts "scp://${USER}@somehost:${PORT}/${COPY}" ${DIR} || fail "copy failed"
+ cmp ${COPY} ${DIR}/copy || fail "corrupted copy"
-verbose "$tid: recursive local dir to remote dir"
-scpclean
-rm -rf ${DIR2}
-cp ${DATA} ${DIR}/copy
-$SCP $scpopts -r ${DIR} "scp://${USER}@somehost:${PORT}/${DIR2}" || fail "copy failed"
-for i in $(cd ${DIR} && echo *); do
- cmp ${DIR}/$i ${DIR2}/$i || fail "corrupted copy"
-done
+ verbose "$tag: recursive local dir to remote dir"
+ scpclean
+ rm -rf ${DIR2}
+ cp ${DATA} ${DIR}/copy
+ $SCP $scpopts -r ${DIR} "scp://${USER}@somehost:${PORT}/${DIR2}" || fail "copy failed"
+ for i in $(cd ${DIR} && echo *); do
+ cmp ${DIR}/$i ${DIR2}/$i || fail "corrupted copy"
+ done
-verbose "$tid: recursive remote dir to local dir"
-scpclean
-rm -rf ${DIR2}
-cp ${DATA} ${DIR}/copy
-$SCP $scpopts -r "scp://${USER}@somehost:${PORT}/${DIR}" ${DIR2} || fail "copy failed"
-for i in $(cd ${DIR} && echo *); do
- cmp ${DIR}/$i ${DIR2}/$i || fail "corrupted copy"
-done
+ verbose "$tag: recursive remote dir to local dir"
+ scpclean
+ rm -rf ${DIR2}
+ cp ${DATA} ${DIR}/copy
+ $SCP $scpopts -r "scp://${USER}@somehost:${PORT}/${DIR}" ${DIR2} || fail "copy failed"
+ for i in $(cd ${DIR} && echo *); do
+ cmp ${DIR}/$i ${DIR2}/$i || fail "corrupted copy"
+ done
-# TODO: scp -3
+ # TODO: scp -3
+done
scpclean
rm -f ${OBJ}/scp-ssh-wrapper.exe
diff --git a/regress/scp.sh b/regress/scp.sh
index 62400efad..358a8df66 100644
--- a/regress/scp.sh
+++ b/regress/scp.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: scp.sh,v 1.11 2019/07/19 03:45:44 djm Exp $
+# $OpenBSD: scp.sh,v 1.13 2021/08/10 03:35:45 djm Exp $
# Placed in the Public Domain.
tid="scp"
@@ -19,7 +19,6 @@ DIR2=${COPY}.dd2
SRC=`dirname ${SCRIPT}`
cp ${SRC}/scp-ssh-wrapper.sh ${OBJ}/scp-ssh-wrapper.scp
chmod 755 ${OBJ}/scp-ssh-wrapper.scp
-scpopts="-q -S ${OBJ}/scp-ssh-wrapper.scp"
export SCP # used in scp-ssh-wrapper.scp
scpclean() {
@@ -28,109 +27,117 @@ scpclean() {
chmod 755 ${DIR} ${DIR2}
}
-verbose "$tid: simple copy local file to local file"
-scpclean
-$SCP $scpopts ${DATA} ${COPY} || fail "copy failed"
-cmp ${DATA} ${COPY} || fail "corrupted copy"
-
-verbose "$tid: simple copy local file to remote file"
-scpclean
-$SCP $scpopts ${DATA} somehost:${COPY} || fail "copy failed"
-cmp ${DATA} ${COPY} || fail "corrupted copy"
-
-verbose "$tid: simple copy remote file to local file"
-scpclean
-$SCP $scpopts somehost:${DATA} ${COPY} || fail "copy failed"
-cmp ${DATA} ${COPY} || fail "corrupted copy"
-
-verbose "$tid: simple copy local file to remote dir"
-scpclean
-cp ${DATA} ${COPY}
-$SCP $scpopts ${COPY} somehost:${DIR} || fail "copy failed"
-cmp ${COPY} ${DIR}/copy || fail "corrupted copy"
-
-verbose "$tid: simple copy local file to local dir"
-scpclean
-cp ${DATA} ${COPY}
-$SCP $scpopts ${COPY} ${DIR} || fail "copy failed"
-cmp ${COPY} ${DIR}/copy || fail "corrupted copy"
-
-verbose "$tid: simple copy remote file to local dir"
-scpclean
-cp ${DATA} ${COPY}
-$SCP $scpopts somehost:${COPY} ${DIR} || fail "copy failed"
-cmp ${COPY} ${DIR}/copy || fail "corrupted copy"
+for mode in scp sftp ; do
+ tag="$tid: $mode mode"
+ if test $mode = scp ; then
+ scpopts="-O -q -S ${OBJ}/scp-ssh-wrapper.scp"
+ else
+ scpopts="-s -D ${SFTPSERVER}"
+ fi
+ verbose "tid: simple copy local file to local file"
+ scpclean
+ $SCP $scpopts ${DATA} ${COPY} || fail "copy failed"
+ cmp ${DATA} ${COPY} || fail "corrupted copy"
-verbose "$tid: recursive local dir to remote dir"
-scpclean
-rm -rf ${DIR2}
-cp ${DATA} ${DIR}/copy
-$SCP $scpopts -r ${DIR} somehost:${DIR2} || fail "copy failed"
-diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy"
+ verbose "$tag: simple copy local file to remote file"
+ scpclean
+ $SCP $scpopts ${DATA} somehost:${COPY} || fail "copy failed"
+ cmp ${DATA} ${COPY} || fail "corrupted copy"
-verbose "$tid: recursive local dir to local dir"
-scpclean
-rm -rf ${DIR2}
-cp ${DATA} ${DIR}/copy
-$SCP $scpopts -r ${DIR} ${DIR2} || fail "copy failed"
-diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy"
+ verbose "$tag: simple copy remote file to local file"
+ scpclean
+ $SCP $scpopts somehost:${DATA} ${COPY} || fail "copy failed"
+ cmp ${DATA} ${COPY} || fail "corrupted copy"
-verbose "$tid: recursive remote dir to local dir"
-scpclean
-rm -rf ${DIR2}
-cp ${DATA} ${DIR}/copy
-$SCP $scpopts -r somehost:${DIR} ${DIR2} || fail "copy failed"
-diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy"
+ verbose "$tag: simple copy local file to remote dir"
+ scpclean
+ cp ${DATA} ${COPY}
+ $SCP $scpopts ${COPY} somehost:${DIR} || fail "copy failed"
+ cmp ${COPY} ${DIR}/copy || fail "corrupted copy"
-verbose "$tid: shell metacharacters"
-scpclean
-(cd ${DIR} && \
-touch '`touch metachartest`' && \
-$SCP $scpopts *metachar* ${DIR2} 2>/dev/null; \
-[ ! -f metachartest ] ) || fail "shell metacharacters"
+ verbose "$tag: simple copy local file to local dir"
+ scpclean
+ cp ${DATA} ${COPY}
+ $SCP $scpopts ${COPY} ${DIR} || fail "copy failed"
+ cmp ${COPY} ${DIR}/copy || fail "corrupted copy"
-if [ ! -z "$SUDO" ]; then
- verbose "$tid: skipped file after scp -p with failed chown+utimes"
+ verbose "$tag: simple copy remote file to local dir"
scpclean
- cp -p ${DATA} ${DIR}/copy
- cp -p ${DATA} ${DIR}/copy2
- cp ${DATA} ${DIR2}/copy
- chmod 660 ${DIR2}/copy
- $SUDO chown root ${DIR2}/copy
- $SCP -p $scpopts somehost:${DIR}/\* ${DIR2} >/dev/null 2>&1
- $SUDO diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy"
- $SUDO rm ${DIR2}/copy
-fi
+ cp ${DATA} ${COPY}
+ $SCP $scpopts somehost:${COPY} ${DIR} || fail "copy failed"
+ cmp ${COPY} ${DIR}/copy || fail "corrupted copy"
-for i in 0 1 2 3 4 5 6 7; do
- verbose "$tid: disallow bad server #$i"
- SCPTESTMODE=badserver_$i
- export DIR SCPTESTMODE
+ verbose "$tag: recursive local dir to remote dir"
scpclean
- $SCP $scpopts somehost:${DATA} ${DIR} >/dev/null 2>/dev/null
- [ -d {$DIR}/rootpathdir ] && fail "allows dir relative to root dir"
- [ -d ${DIR}/dotpathdir ] && fail "allows dir creation in non-recursive mode"
+ rm -rf ${DIR2}
+ cp ${DATA} ${DIR}/copy
+ $SCP $scpopts -r ${DIR} somehost:${DIR2} || fail "copy failed"
+ diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy"
+ verbose "$tag: recursive local dir to local dir"
scpclean
- $SCP -r $scpopts somehost:${DATA} ${DIR2} >/dev/null 2>/dev/null
- [ -d ${DIR}/dotpathdir ] && fail "allows dir creation outside of subdir"
+ rm -rf ${DIR2}
+ cp ${DATA} ${DIR}/copy
+ $SCP $scpopts -r ${DIR} ${DIR2} || fail "copy failed"
+ diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy"
+ verbose "$tag: recursive remote dir to local dir"
scpclean
- $SCP -pr $scpopts somehost:${DATA} ${DIR2} >/dev/null 2>/dev/null
- [ ! -w ${DIR2} ] && fail "allows target root attribute change"
+ rm -rf ${DIR2}
+ cp ${DATA} ${DIR}/copy
+ $SCP $scpopts -r somehost:${DIR} ${DIR2} || fail "copy failed"
+ diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy"
+ verbose "$tag: shell metacharacters"
scpclean
- $SCP $scpopts somehost:${DATA} ${DIR2} >/dev/null 2>/dev/null
- [ -e ${DIR2}/extrafile ] && fail "allows unauth object creation"
- rm -f ${DIR2}/extrafile
+ (cd ${DIR} && \
+ touch '`touch metachartest`' && \
+ $SCP $scpopts *metachar* ${DIR2} 2>/dev/null; \
+ [ ! -f metachartest ] ) || fail "shell metacharacters"
+
+ if [ ! -z "$SUDO" ]; then
+ verbose "$tag: skipped file after scp -p with failed chown+utimes"
+ scpclean
+ cp -p ${DATA} ${DIR}/copy
+ cp -p ${DATA} ${DIR}/copy2
+ cp ${DATA} ${DIR2}/copy
+ chmod 660 ${DIR2}/copy
+ $SUDO chown root ${DIR2}/copy
+ $SCP -p $scpopts somehost:${DIR}/\* ${DIR2} >/dev/null 2>&1
+ $SUDO diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy"
+ $SUDO rm ${DIR2}/copy
+ fi
+
+ for i in 0 1 2 3 4 5 6 7; do
+ verbose "$tag: disallow bad server #$i"
+ SCPTESTMODE=badserver_$i
+ export DIR SCPTESTMODE
+ scpclean
+ $SCP $scpopts somehost:${DATA} ${DIR} >/dev/null 2>/dev/null
+ [ -d {$DIR}/rootpathdir ] && fail "allows dir relative to root dir"
+ [ -d ${DIR}/dotpathdir ] && fail "allows dir creation in non-recursive mode"
+
+ scpclean
+ $SCP -r $scpopts somehost:${DATA} ${DIR2} >/dev/null 2>/dev/null
+ [ -d ${DIR}/dotpathdir ] && fail "allows dir creation outside of subdir"
+
+ scpclean
+ $SCP -pr $scpopts somehost:${DATA} ${DIR2} >/dev/null 2>/dev/null
+ [ ! -w ${DIR2} ] && fail "allows target root attribute change"
+
+ scpclean
+ $SCP $scpopts somehost:${DATA} ${DIR2} >/dev/null 2>/dev/null
+ [ -e ${DIR2}/extrafile ] && fail "allows unauth object creation"
+ rm -f ${DIR2}/extrafile
+ done
+
+ verbose "$tag: detect non-directory target"
+ scpclean
+ echo a > ${COPY}
+ echo b > ${COPY2}
+ $SCP $scpopts ${DATA} ${COPY} ${COPY2}
+ cmp ${COPY} ${COPY2} >/dev/null && fail "corrupt target"
done
-verbose "$tid: detect non-directory target"
-scpclean
-echo a > ${COPY}
-echo b > ${COPY2}
-$SCP $scpopts ${DATA} ${COPY} ${COPY2}
-cmp ${COPY} ${COPY2} >/dev/null && fail "corrupt target"
-
scpclean
rm -f ${OBJ}/scp-ssh-wrapper.scp
diff --git a/regress/scp3.sh b/regress/scp3.sh
new file mode 100644
index 000000000..f71b15677
--- /dev/null
+++ b/regress/scp3.sh
@@ -0,0 +1,60 @@
+# $OpenBSD: scp3.sh,v 1.3 2021/08/10 03:35:45 djm Exp $
+# Placed in the Public Domain.
+
+tid="scp3"
+
+#set -x
+
+COPY2=${OBJ}/copy2
+DIR=${COPY}.dd
+DIR2=${COPY}.dd2
+
+SRC=`dirname ${SCRIPT}`
+cp ${SRC}/scp-ssh-wrapper.sh ${OBJ}/scp-ssh-wrapper.scp
+chmod 755 ${OBJ}/scp-ssh-wrapper.scp
+export SCP # used in scp-ssh-wrapper.scp
+
+scpclean() {
+ rm -rf ${COPY} ${COPY2} ${DIR} ${DIR2}
+ mkdir ${DIR} ${DIR2}
+ chmod 755 ${DIR} ${DIR2}
+}
+
+for mode in scp sftp ; do
+ scpopts="-F${OBJ}/ssh_proxy -S ${SSH} -q"
+ tag="$tid: $mode mode"
+ if test $mode = scp ; then
+ scpopts="$scpopts -O"
+ else
+ scpopts="-s -D ${SFTPSERVER}"
+ fi
+
+ verbose "$tag: simple copy remote file to remote file"
+ scpclean
+ $SCP $scpopts -3 hostA:${DATA} hostB:${COPY} || fail "copy failed"
+ cmp ${DATA} ${COPY} || fail "corrupted copy"
+
+ verbose "$tag: simple copy remote file to remote dir"
+ scpclean
+ cp ${DATA} ${COPY}
+ $SCP $scpopts -3 hostA:${COPY} hostB:${DIR} || fail "copy failed"
+ cmp ${COPY} ${DIR}/copy || fail "corrupted copy"
+
+ verbose "$tag: recursive remote dir to remote dir"
+ scpclean
+ rm -rf ${DIR2}
+ cp ${DATA} ${DIR}/copy
+ $SCP $scpopts -3r hostA:${DIR} hostB:${DIR2} || fail "copy failed"
+ diff -r ${DIR} ${DIR2} || fail "corrupted copy"
+ diff -r ${DIR2} ${DIR} || fail "corrupted copy"
+
+ verbose "$tag: detect non-directory target"
+ scpclean
+ echo a > ${COPY}
+ echo b > ${COPY2}
+ $SCP $scpopts -3 hostA:${DATA} hostA:${COPY} hostB:${COPY2}
+ cmp ${COPY} ${COPY2} >/dev/null && fail "corrupt target"
+done
+
+scpclean
+rm -f ${OBJ}/scp-ssh-wrapper.exe
diff --git a/regress/servcfginclude.sh b/regress/servcfginclude.sh
index b25c8faa8..518a703d1 100644
--- a/regress/servcfginclude.sh
+++ b/regress/servcfginclude.sh
@@ -9,17 +9,17 @@ Match host a
Match host b
Banner /bb
- Include $OBJ/sshd_config.i.*
+ Include $OBJ/sshd_config.i.* # comment
Match host c
- Include $OBJ/sshd_config.i.*
+ Include $OBJ/sshd_config.i.* # comment
Banner /cc
Match host m
Include $OBJ/sshd_config.i.*
Match Host d
- Banner /dd
+ Banner /dd # comment
Match Host e
Banner /ee
@@ -64,7 +64,7 @@ Match host a
Match host b
Banner /bbbb
-Match host c
+Match host c # comment
Banner /cccc
Match Host d
@@ -146,9 +146,43 @@ Include
_EOF
trace "disallow invalid with no argument"
-${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i.x \
+${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i.x -T \
-C "host=x,user=test,addr=127.0.0.1" 2>/dev/null && \
fail "sshd allowed Include with no argument"
+# Ensure the Include before any Match block works as expected (bug #3122)
+cat > $OBJ/sshd_config.i << _EOF
+Banner /xx
+HostKey $OBJ/host.ssh-ed25519
+Include $OBJ/sshd_config.i.2
+Match host a
+ Banner /aaaa
+_EOF
+cat > $OBJ/sshd_config.i.2 << _EOF
+Match host a
+ Banner /aa
+_EOF
+
+trace "Include before match blocks"
+trial a /aa "included file before match blocks is properly evaluated"
+
+# Port in included file is correctly interpretted (bug #3169)
+cat > $OBJ/sshd_config.i << _EOF
+Include $OBJ/sshd_config.i.2
+Port 7722
+_EOF
+cat > $OBJ/sshd_config.i.2 << _EOF
+HostKey $OBJ/host.ssh-ed25519
+_EOF
+
+trace "Port after included files"
+${SUDO} ${REAL_SSHD} -f $OBJ/sshd_config.i -T \
+ -C "host=x,user=test,addr=127.0.0.1" > $OBJ/sshd_config.out || \
+ fail "failed to parse Port after included files"
+_port=`grep -i '^port ' $OBJ/sshd_config.out | awk '{print $2}'`
+if test "x7722" != "x$_port" ; then
+ fail "The Port in included file was intertepretted wrongly. Expected 7722, got $_port"
+fi
+
# cleanup
rm -f $OBJ/sshd_config.i $OBJ/sshd_config.i.* $OBJ/sshd_config.out
diff --git a/regress/sftp-chroot.sh b/regress/sftp-chroot.sh
index 5acc4d2de..a7766fe63 100644
--- a/regress/sftp-chroot.sh
+++ b/regress/sftp-chroot.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: sftp-chroot.sh,v 1.7 2018/11/22 08:48:32 dtucker Exp $
+# $OpenBSD: sftp-chroot.sh,v 1.8 2021/09/01 00:50:27 dtucker Exp $
# Placed in the Public Domain.
tid="sftp in chroot"
@@ -9,14 +9,11 @@ PRIVDATA=${CHROOT}/${FILENAME}
trap "${SUDO} rm -f ${PRIVDATA}" 0
if [ -z "$SUDO" -a ! -w /var/run ]; then
- echo "need SUDO to create file in /var/run, test won't work without"
- echo SKIPPED
- exit 0
+ skip "need SUDO to create file in /var/run, test won't work without"
fi
if ! $OBJ/check-perm -m chroot "$CHROOT" ; then
- echo "skipped: $CHROOT is unsuitable as ChrootDirectory"
- exit 0
+ skip "$CHROOT is unsuitable as ChrootDirectory"
fi
$SUDO sh -c "echo mekmitastdigoat > $PRIVDATA" || \
diff --git a/regress/sftp-perm.sh b/regress/sftp-perm.sh
index 304ca0ac5..de96a14da 100644
--- a/regress/sftp-perm.sh
+++ b/regress/sftp-perm.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: sftp-perm.sh,v 1.2 2013/10/17 22:00:18 djm Exp $
+# $OpenBSD: sftp-perm.sh,v 1.3 2021/03/31 21:59:26 djm Exp $
# Placed in the Public Domain.
tid="sftp permissions"
@@ -220,13 +220,15 @@ perm_test \
"test ! -d ${COPY}.dd" \
"test -d ${COPY}.dd"
-perm_test \
- "posix-rename" \
- "realpath,stat,lstat" \
- "rename $COPY ${COPY}.1" \
- "touch $COPY" \
- "test -f ${COPY}.1 -a ! -f $COPY" \
- "test -f $COPY -a ! -f ${COPY}.1"
+# Can't readily test this because the client falls back to traditional rename.
+# XXX maybe there is a behaviorial difference we can test for?
+#perm_test \
+# "posix-rename" \
+# "realpath,stat,lstat" \
+# "rename $COPY ${COPY}.1" \
+# "touch $COPY" \
+# "test -f ${COPY}.1 -a ! -f $COPY" \
+# "test -f $COPY -a ! -f ${COPY}.1"
perm_test \
"rename" \
diff --git a/regress/ssh2putty.sh b/regress/ssh2putty.sh
index dcb975d95..9b0831039 100755
--- a/regress/ssh2putty.sh
+++ b/regress/ssh2putty.sh
@@ -1,5 +1,5 @@
#!/bin/sh
-# $OpenBSD: ssh2putty.sh,v 1.5 2019/11/21 05:18:47 tb Exp $
+# $OpenBSD: ssh2putty.sh,v 1.9 2021/07/25 12:13:03 dtucker Exp $
if test "x$1" = "x" -o "x$2" = "x" -o "x$3" = "x" ; then
echo "Usage: ssh2putty hostname port ssh-private-key"
@@ -10,6 +10,8 @@ HOST=$1
PORT=$2
KEYFILE=$3
+OPENSSL_BIN="${OPENSSL_BIN:-openssl}"
+
# XXX - support DSA keys too
if grep "BEGIN RSA PRIVATE KEY" $KEYFILE >/dev/null 2>&1 ; then
:
@@ -19,13 +21,13 @@ else
fi
public_exponent=`
- openssl rsa -noout -text -in $KEYFILE | grep ^publicExponent |
+ $OPENSSL_BIN rsa -noout -text -in $KEYFILE | grep ^publicExponent |
sed 's/.*(//;s/).*//'
`
test $? -ne 0 && exit 1
modulus=`
- openssl rsa -noout -modulus -in $KEYFILE | grep ^Modulus= |
+ $OPENSSL_BIN rsa -noout -modulus -in $KEYFILE | grep ^Modulus= |
sed 's/^Modulus=/0x/' | tr A-Z a-z
`
test $? -ne 0 && exit 1
diff --git a/regress/sshcfgparse.sh b/regress/sshcfgparse.sh
index fc72a0a71..504853d32 100644
--- a/regress/sshcfgparse.sh
+++ b/regress/sshcfgparse.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: sshcfgparse.sh,v 1.6 2019/12/21 02:33:07 djm Exp $
+# $OpenBSD: sshcfgparse.sh,v 1.9 2021/06/08 07:05:27 dtucker Exp $
# Placed in the Public Domain.
tid="ssh config parse"
@@ -32,7 +32,7 @@ expect_result_absent() {
verbose "reparse minimal config"
(${SSH} -G -F $OBJ/ssh_config somehost >$OBJ/ssh_config.1 &&
${SSH} -G -F $OBJ/ssh_config.1 somehost >$OBJ/ssh_config.2 &&
- diff $OBJ/ssh_config.1 $OBJ/ssh_config.2) || fail "reparse minimal config"
+ diff $OBJ/ssh_config.1 $OBJ/ssh_config.2) || fail "failed to reparse minimal"
verbose "ssh -W opts"
f=`${SSH} -GF $OBJ/ssh_config host | awk '/exitonforwardfailure/{print $2}'`
@@ -62,34 +62,34 @@ test "$f" = "bar" || fail "user first match -l, expected 'bar' got '$f'"
f=`${SSH} -GF $OBJ/ssh_config baz@host -o user=foo -l bar baz@host | awk '/^user /{print $2}'`
test "$f" = "baz" || fail "user first match user@host, expected 'baz' got '$f'"
-verbose "pubkeyacceptedkeytypes"
+verbose "pubkeyacceptedalgorithms"
# Default set
-f=`${SSH} -GF none host | awk '/^pubkeyacceptedkeytypes /{print $2}'`
+f=`${SSH} -GF none host | awk '/^pubkeyacceptedalgorithms /{print $2}'`
expect_result_present "$f" "ssh-ed25519" "ssh-ed25519-cert-v01.*"
expect_result_absent "$f" "ssh-dss"
# Explicit override
-f=`${SSH} -GF none -opubkeyacceptedkeytypes=ssh-ed25519 host | \
- awk '/^pubkeyacceptedkeytypes /{print $2}'`
+f=`${SSH} -GF none -opubkeyacceptedalgorithms=ssh-ed25519 host | \
+ awk '/^pubkeyacceptedalgorithms /{print $2}'`
expect_result_present "$f" "ssh-ed25519"
expect_result_absent "$f" "ssh-ed25519-cert-v01.*" "ssh-dss"
# Removal from default set
-f=`${SSH} -GF none -opubkeyacceptedkeytypes=-ssh-ed25519-cert* host | \
- awk '/^pubkeyacceptedkeytypes /{print $2}'`
+f=`${SSH} -GF none -opubkeyacceptedalgorithms=-ssh-ed25519-cert* host | \
+ awk '/^pubkeyacceptedalgorithms /{print $2}'`
expect_result_present "$f" "ssh-ed25519"
expect_result_absent "$f" "ssh-ed25519-cert-v01.*" "ssh-dss"
-f=`${SSH} -GF none -opubkeyacceptedkeytypes=-ssh-ed25519 host | \
- awk '/^pubkeyacceptedkeytypes /{print $2}'`
+f=`${SSH} -GF none -opubkeyacceptedalgorithms=-ssh-ed25519 host | \
+ awk '/^pubkeyacceptedalgorithms /{print $2}'`
expect_result_present "$f" "ssh-ed25519-cert-v01.*"
expect_result_absent "$f" "ssh-ed25519" "ssh-dss"
# Append to default set.
# This is not tested when built !WITH_OPENSSL
if [ "$dsa" = "1" ]; then
- f=`${SSH} -GF none -opubkeyacceptedkeytypes=+ssh-dss-cert* host | \
- awk '/^pubkeyacceptedkeytypes /{print $2}'`
+ f=`${SSH} -GF none -opubkeyacceptedalgorithms=+ssh-dss-cert* host | \
+ awk '/^pubkeyacceptedalgorithms /{print $2}'`
expect_result_present "$f" "ssh-ed25519" "ssh-dss-cert-v01.*"
expect_result_absent "$f" "ssh-dss"
- f=`${SSH} -GF none -opubkeyacceptedkeytypes=+ssh-dss host | \
- awk '/^pubkeyacceptedkeytypes /{print $2}'`
+ f=`${SSH} -GF none -opubkeyacceptedalgorithms=+ssh-dss host | \
+ awk '/^pubkeyacceptedalgorithms /{print $2}'`
expect_result_present "$f" "ssh-ed25519" "ssh-ed25519-cert-v01.*" "ssh-dss"
expect_result_absent "$f" "ssh-dss-cert-v01.*"
fi
@@ -104,5 +104,16 @@ expect_result_present "$f" "yes"
f=`${SSH} -GF none '-oforwardagent=SSH_AUTH_SOCK.forward' host | awk '/^forwardagent /{print$2}'`
expect_result_present "$f" "SSH_AUTH_SOCK.forward"
+verbose "command line override"
+cat >$OBJ/ssh_config.0 <<EOD
+Host *
+ IPQoS af21 cs1
+ TunnelDevice 1:2
+EOD
+f=`${SSH} -GF $OBJ/ssh_config.0 -oipqos=cs1 host | awk '/^ipqos /{print$2}'`
+expect_result_present "$f" "cs1"
+f=`${SSH} -GF $OBJ/ssh_config.0 -otunneldevice=3:4 host | awk '/^tunneldevice /{print$2}'`
+expect_result_present "$f" "3:4"
+
# cleanup
rm -f $OBJ/ssh_config.[012]
diff --git a/regress/sshfp-connect.sh b/regress/sshfp-connect.sh
new file mode 100644
index 000000000..f78646922
--- /dev/null
+++ b/regress/sshfp-connect.sh
@@ -0,0 +1,66 @@
+# $OpenBSD: sshfp-connect.sh,v 1.4 2021/09/01 00:50:27 dtucker Exp $
+# Placed in the Public Domain.
+
+# This test requires external setup and thus is skipped unless
+# TEST_SSH_SSHFP_DOMAIN is set. It requires:
+# 1) A DNSSEC-enabled domain, which TEST_SSH_SSHFP_DOMAIN points to.
+# 2) A DNSSEC-validating resolver such as unwind(8).
+# 3) The following SSHFP records with fingerprints from rsa_openssh.pub
+# in that domain that are expected to succeed:
+# sshtest: valid sha1 and sha256 fingerprints.
+# sshtest-sha{1,256}, : valid fingerprints for that type only.
+# and the following records that are expected to fail:
+# sshtest-bad: invalid sha1 fingerprint and good sha256 fingerprint
+# sshtest-sha{1,256}-bad: invalid fingerprints for that type only.
+#
+# sshtest IN SSHFP 1 1 99C79CC09F5F81069CC017CDF9552CFC94B3B929
+# sshtest IN SSHFP 1 2 E30D6B9EB7A4DE495324E4D5870B8220577993EA6AF417E8E4A4F1C5 BF01A9B6
+# sshtest-sha1 IN SSHFP 1 1 99C79CC09F5F81069CC017CDF9552CFC94B3B929
+# sshtest-sha256 IN SSHFP 1 2 E30D6B9EB7A4DE495324E4D5870B8220577993EA6AF417E8E4A4F1C5 BF01A9B6
+# sshtest-bad IN SSHFP 1 2 E30D6B9EB7A4DE495324E4D5870B8220577993EA6AF417E8E4A4F1C5 BF01A9B6
+# sshtest-bad IN SSHFP 1 1 99C79CC09F5F81069CC017CDF9552CFC94B3B928
+# sshtest-sha1-bad IN SSHFP 1 1 99D79CC09F5F81069CC017CDF9552CFC94B3B929
+# sshtest-sha256-bad IN SSHFP 1 2 E30D6B9EB7A4DE495324E4D5870B8220577993EA6AF417E8E4A4F1C5 BF01A9B5
+
+tid="sshfp connect"
+
+if ! $SSH -Q key-plain | grep ssh-rsa >/dev/null; then
+ skip "RSA keys not supported."
+elif [ -z "${TEST_SSH_SSHFP_DOMAIN}" ]; then
+ skip "TEST_SSH_SSHFP_DOMAIN not set."
+else
+ # Set RSA host key to match fingerprints above.
+ mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig
+ $SUDO cp $SRC/rsa_openssh.prv $OBJ/host.ssh-rsa
+ $SUDO chmod 600 $OBJ/host.ssh-rsa
+ sed -e "s|$OBJ/ssh-rsa|$OBJ/host.ssh-rsa|" \
+ $OBJ/sshd_proxy.orig > $OBJ/sshd_proxy
+
+ # Zero out known hosts and key aliases to force use of SSHFP records.
+ > $OBJ/known_hosts
+ mv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig
+ sed -e "/HostKeyAlias.*localhost-with-alias/d" \
+ -e "/Hostname.*127.0.0.1/d" \
+ $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy
+
+ for n in sshtest sshtest-sha1 sshtest-sha256; do
+ trace "sshfp connect $n good fingerprint"
+ host="${n}.dtucker.net"
+ opts="-F $OBJ/ssh_proxy -o VerifyHostKeyDNS=yes "
+ opts="$opts -o HostKeyAlgorithms=rsa-sha2-512,rsa-sha2-256"
+ host="${n}.${TEST_SSH_SSHFP_DOMAIN}"
+ SSH_CONNECTION=`${SSH} $opts $host 'echo $SSH_CONNECTION'`
+ if [ $? -ne 0 ]; then
+ fail "ssh sshfp connect failed"
+ fi
+ if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then
+ fail "bad SSH_CONNECTION: $SSH_CONNECTION"
+ fi
+
+ trace "sshfp connect $n bad fingerprint"
+ host="${n}-bad.${TEST_SSH_SSHFP_DOMAIN}"
+ if ${SSH} $opts ${host} true; then
+ fail "sshfp-connect succeeded with bad SSHFP record"
+ fi
+ done
+fi
diff --git a/regress/sshsig.sh b/regress/sshsig.sh
index 1e2f9dda4..fc300a8dc 100644
--- a/regress/sshsig.sh
+++ b/regress/sshsig.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: sshsig.sh,v 1.4 2020/03/13 03:18:45 djm Exp $
+# $OpenBSD: sshsig.sh,v 1.7 2021/08/11 08:55:04 djm Exp $
# Placed in the Public Domain.
tid="sshsig"
@@ -12,12 +12,13 @@ sig_namespace="test-$$"
sig_principal="user-$$@example.com"
# Make a "wrong key"
-${SSHKEYGEN} -t ed25519 -f $OBJ/wrong-key -C "wrong trousers, Grommit" -N '' \
+${SSHKEYGEN} -q -t ed25519 -f $OBJ/wrong-key \
+ -C "wrong trousers, Grommit" -N '' \
|| fatal "couldn't generate key"
WRONG=$OBJ/wrong-key.pub
# Make a CA key.
-${SSHKEYGEN} -t ed25519 -f $OBJ/sigca-key -C "CA" -N '' \
+${SSHKEYGEN} -q -t ed25519 -f $OBJ/sigca-key -C "CA" -N '' \
|| fatal "couldn't generate key"
CA_PRIV=$OBJ/sigca-key
CA_PUB=$OBJ/sigca-key.pub
@@ -63,6 +64,17 @@ for t in $SIGNKEYS; do
< $DATA >/dev/null 2>&1 || \
fail "failed signature for $t key w/ limited namespace"
+ (printf "$sig_principal namespaces=\"$sig_namespace,whatever\" ";
+ cat $pubkey) > $OBJ/allowed_signers
+ ${SSHKEYGEN} -q -Y verify -s $sigfile -n $sig_namespace \
+ -I $sig_principal -f $OBJ/allowed_signers \
+ -O print-pubkey \
+ < $DATA | cut -d' ' -f1-2 > ${OBJ}/${keybase}-fromsig.pub || \
+ fail "failed signature for $t key w/ print-pubkey"
+ cut -d' ' -f1-2 ${OBJ}/${keybase}.pub > ${OBJ}/${keybase}-strip.pub
+ diff -r ${OBJ}/${keybase}-strip.pub ${OBJ}/${keybase}-fromsig.pub || \
+ fail "print-pubkey differs from signature key"
+
# Invalid option
(printf "$sig_principal octopus " ; cat $pubkey) > $OBJ/allowed_signers
${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
@@ -106,6 +118,34 @@ for t in $SIGNKEYS; do
< $DATA >/dev/null 2>&1 && \
fail "accepted signature for $t key with excluded namespace"
+ ( printf "$sig_principal " ;
+ printf "valid-after=\"19800101\",valid-before=\"19900101\" " ;
+ cat $pubkey) > $OBJ/allowed_signers
+
+ # key lifespan valid
+ ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
+ -I $sig_principal -f $OBJ/allowed_signers \
+ -Overify-time=19850101 \
+ < $DATA >/dev/null 2>&1 || \
+ fail "failed signature for $t key with valid expiry interval"
+ # key not yet valid
+ ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
+ -I $sig_principal -f $OBJ/allowed_signers \
+ -Overify-time=19790101 \
+ < $DATA >/dev/null 2>&1 && \
+ fail "failed signature for $t not-yet-valid key"
+ # key expired
+ ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
+ -I $sig_principal -f $OBJ/allowed_signers \
+ -Overify-time=19910101 \
+ < $DATA >/dev/null 2>&1 && \
+ fail "failed signature for $t with expired key"
+ # NB. assumes we're not running this test in the 1980s
+ ${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
+ -I $sig_principal -f $OBJ/allowed_signers \
+ < $DATA >/dev/null 2>&1 && \
+ fail "failed signature for $t with expired key"
+
# public key in revoked keys file
cat $pubkey > $OBJ/revoked_keys
(printf "$sig_principal namespaces=\"whatever\" " ;
@@ -116,7 +156,7 @@ for t in $SIGNKEYS; do
< $DATA >/dev/null 2>&1 && \
fail "accepted signature for $t key, but key is in revoked_keys"
- # public key not revoked, but other are present in revoked_keysfile
+ # public key not revoked, but others are present in revoked_keysfile
cat $WRONG > $OBJ/revoked_keys
(printf "$sig_principal " ; cat $pubkey) > $OBJ/allowed_signers
${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
@@ -168,7 +208,7 @@ for t in $SIGNKEYS; do
fail "failed signature for $t cert"
# signing key listed as cert-authority
- (printf "$sig_principal cert-authority" ;
+ (printf "$sig_principal cert-authority " ;
cat $pubkey) > $OBJ/allowed_signers
${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
-I $sig_principal -f $OBJ/allowed_signers \
@@ -183,7 +223,7 @@ for t in $SIGNKEYS; do
fail "accepted signature for $t cert with CA not marked"
# mismatch between cert principal and file
- (printf "josef.k@example.com cert-authority" ;
+ (printf "josef.k@example.com cert-authority " ;
cat $CA_PUB) > $OBJ/allowed_signers
${SSHKEYGEN} -vvv -Y verify -s $sigfile -n $sig_namespace \
-I $sig_principal -f $OBJ/allowed_signers \
diff --git a/regress/test-exec.sh b/regress/test-exec.sh
index 5dc975d07..415422ef5 100644
--- a/regress/test-exec.sh
+++ b/regress/test-exec.sh
@@ -1,21 +1,11 @@
-# $OpenBSD: test-exec.sh,v 1.76 2020/04/04 23:04:41 dtucker Exp $
+# $OpenBSD: test-exec.sh,v 1.87 2021/09/01 00:50:27 dtucker Exp $
# Placed in the Public Domain.
#SUDO=sudo
-# Unbreak GNU head(1)
-_POSIX2_VERSION=199209
-export _POSIX2_VERSION
-
-case `uname -s 2>/dev/null` in
-OSF1*)
- BIN_SH=xpg4
- export BIN_SH
- ;;
-CYGWIN*)
- os=cygwin
- ;;
-esac
+if [ ! -x "$TEST_SSH_ELAPSED_TIMES" ]; then
+ STARTTIME=`date '+%s'`
+fi
if [ ! -z "$TEST_SSH_PORT" ]; then
PORT="$TEST_SSH_PORT"
@@ -23,26 +13,6 @@ else
PORT=4242
fi
-# If configure tells us to use a different egrep, create a wrapper function
-# to call it. This means we don't need to change all the tests that depend
-# on a good implementation.
-if test "x${EGREP}" != "x"; then
- egrep ()
-{
- ${EGREP} "$@"
-}
-fi
-
-if [ -x /usr/ucb/whoami ]; then
- USER=`/usr/ucb/whoami`
-elif whoami >/dev/null 2>&1; then
- USER=`whoami`
-elif logname >/dev/null 2>&1; then
- USER=`logname`
-else
- USER=`id -un`
-fi
-
OBJ=$1
if [ "x$OBJ" = "x" ]; then
echo '$OBJ not defined'
@@ -69,6 +39,46 @@ else
fi
unset SSH_AUTH_SOCK
+# Portable-specific settings.
+
+if [ -x /usr/ucb/whoami ]; then
+ USER=`/usr/ucb/whoami`
+elif whoami >/dev/null 2>&1; then
+ USER=`whoami`
+elif logname >/dev/null 2>&1; then
+ USER=`logname`
+else
+ USER=`id -un`
+fi
+if test -z "$LOGNAME"; then
+ LOGNAME="${USER}"
+ export LOGNAME
+fi
+
+# Unbreak GNU head(1)
+_POSIX2_VERSION=199209
+export _POSIX2_VERSION
+
+case `uname -s 2>/dev/null` in
+OSF1*)
+ BIN_SH=xpg4
+ export BIN_SH
+ ;;
+CYGWIN*)
+ os=cygwin
+ ;;
+esac
+
+# If configure tells us to use a different egrep, create a wrapper function
+# to call it. This means we don't need to change all the tests that depend
+# on a good implementation.
+if test "x${EGREP}" != "x"; then
+ egrep ()
+{
+ ${EGREP} "$@"
+}
+fi
+
SRC=`dirname ${SCRIPT}`
# defaults
@@ -92,6 +102,7 @@ CONCH=conch
# Tools used by multiple tests
NC=$OBJ/netcat
+OPENSSL_BIN="${OPENSSL_BIN:-openssl}"
if [ "x$TEST_SSH_SSH" != "x" ]; then
SSH="${TEST_SSH_SSH}"
@@ -147,6 +158,9 @@ fi
if [ "x$TEST_SSH_SK_HELPER" != "x" ]; then
SSH_SK_HELPER="${TEST_SSH_SK_HELPER}"
fi
+if [ "x$TEST_SSH_OPENSSL" != "x" ]; then
+ OPENSSL_BIN="${TEST_SSH_OPENSSL}"
+fi
# Path to sshd must be absolute for rexec
case "$SSHD" in
@@ -242,10 +256,15 @@ fi
>$TEST_REGRESS_LOGFILE
# Create wrapper ssh with logging. We can't just specify "SSH=ssh -E..."
-# because sftp and scp don't handle spaces in arguments.
+# because sftp and scp don't handle spaces in arguments. scp and sftp like
+# to use -q so we remove those to preserve our debug logging. In the rare
+# instance where -q is desirable -qq is equivalent and is not removed.
SSHLOGWRAP=$OBJ/ssh-log-wrapper.sh
-echo "#!/bin/sh" > $SSHLOGWRAP
-echo "exec ${SSH} -E${TEST_SSH_LOGFILE} "'"$@"' >>$SSHLOGWRAP
+cat >$SSHLOGWRAP <<EOD
+#!/bin/sh
+for i in "\$@";do shift;case "\$i" in -q):;; *) set -- "\$@" "\$i";;esac;done
+exec ${SSH} -E${TEST_SSH_LOGFILE} "\$@"
+EOD
chmod a+rx $OBJ/ssh-log-wrapper.sh
REAL_SSH="$SSH"
@@ -315,10 +334,27 @@ md5 () {
cksum
elif have_prog sum; then
sum
+ elif [ -x ${OPENSSL_BIN} ]; then
+ ${OPENSSL_BIN} md5
else
wc -c
fi
}
+
+# Some platforms don't have hostname at all, but on others uname -n doesn't
+# provide the fully qualified name we need, so in the former case we create
+# our own hostname function.
+if ! have_prog hostname; then
+ hostname() {
+ uname -n
+ }
+fi
+
+make_tmpdir ()
+{
+ SSH_REGRESS_TMP="$($OBJ/mkdtemp openssh-XXXXXXXX)" || \
+ fatal "failed to create temporary directory"
+}
# End of portable specific functions
stop_sshd ()
@@ -352,12 +388,6 @@ stop_sshd ()
fi
}
-make_tmpdir ()
-{
- SSH_REGRESS_TMP="$($OBJ/mkdtemp openssh-XXXXXXXX)" || \
- fatal "failed to create temporary directory"
-}
-
# helper
cleanup ()
{
@@ -372,6 +402,11 @@ cleanup ()
rm -rf "$SSH_REGRESS_TMP"
fi
stop_sshd
+ if [ ! -z "$TEST_SSH_ELAPSED_TIMES" ]; then
+ now=`date '+%s'`
+ elapsed=$(($now - $STARTTIME))
+ echo elapsed $elapsed `basename $SCRIPT .sh`
+ fi
}
start_debug_log ()
@@ -407,12 +442,6 @@ verbose ()
fi
}
-warn ()
-{
- echo "WARNING: $@" >>$TEST_SSH_LOGFILE
- echo "WARNING: $@"
-}
-
fail ()
{
save_debug_log "FAIL: $@"
@@ -433,6 +462,14 @@ fatal ()
exit $RESULT
}
+# Skip remaining tests in script.
+skip ()
+{
+ echo "SKIPPED: $@"
+ cleanup
+ exit $RESULT
+}
+
RESULT=0
PIDFILE=$OBJ/pidfile
@@ -457,7 +494,7 @@ EOF
# but if you aren't careful with permissions then the unit tests could
# be abused to locally escalate privileges.
if [ ! -z "$TEST_SSH_UNSAFE_PERMISSIONS" ]; then
- echo "StrictModes no" >> $OBJ/sshd_config
+ echo " StrictModes no" >> $OBJ/sshd_config
else
# check and warn if excessive permissions are likely to cause failures.
unsafe=""
@@ -485,6 +522,11 @@ EOD
fi
fi
+if [ ! -z "$TEST_SSH_MODULI_FILE" ]; then
+ trace "adding modulifile='$TEST_SSH_MODULI_FILE' to sshd_config"
+ echo " ModuliFile '$TEST_SSH_MODULI_FILE'" >> $OBJ/sshd_config
+fi
+
if [ ! -z "$TEST_SSH_SSHD_CONFOPTS" ]; then
trace "adding sshd_config option $TEST_SSH_SSHD_CONFOPTS"
echo "$TEST_SSH_SSHD_CONFOPTS" >> $OBJ/sshd_config
@@ -574,7 +616,7 @@ for t in ${SSH_HOSTKEY_TYPES}; do
) >> $OBJ/known_hosts
# use key as host key, too
- $SUDO cp $OBJ/$t $OBJ/host.$t
+ (umask 077; $SUDO cp $OBJ/$t $OBJ/host.$t)
echo HostKey $OBJ/host.$t >> $OBJ/sshd_config
# don't use SUDO for proxy connect
@@ -588,10 +630,11 @@ if test -x "$CONCH" ; then
REGRESS_INTEROP_CONCH=yes
fi
-# If PuTTY is present and we are running a PuTTY test, prepare keys and
-# configuration
+# If PuTTY is present, new enough and we are running a PuTTY test, prepare
+# keys and configuration.
REGRESS_INTEROP_PUTTY=no
-if test -x "$PUTTYGEN" -a -x "$PLINK" ; then
+if test -x "$PUTTYGEN" -a -x "$PLINK" &&
+ "$PUTTYGEN" --help 2>&1 | grep -- --new-passphrase >/dev/null; then
REGRESS_INTEROP_PUTTY=yes
fi
case "$SCRIPT" in
@@ -604,13 +647,13 @@ if test "$REGRESS_INTEROP_PUTTY" = "yes" ; then
# Add a PuTTY key to authorized_keys
rm -f ${OBJ}/putty.rsa2
- if ! puttygen -t rsa -o ${OBJ}/putty.rsa2 \
+ if ! "$PUTTYGEN" -t rsa -o ${OBJ}/putty.rsa2 \
--random-device=/dev/urandom \
--new-passphrase /dev/null < /dev/null > /dev/null; then
- echo "Your installed version of PuTTY is too old to support --new-passphrase; trying without (may require manual interaction) ..." >&2
- puttygen -t rsa -o ${OBJ}/putty.rsa2 < /dev/null > /dev/null
+ echo "Your installed version of PuTTY is too old to support --new-passphrase, skipping test" >&2
+ exit 1
fi
- puttygen -O public-openssh ${OBJ}/putty.rsa2 \
+ "$PUTTYGEN" -O public-openssh ${OBJ}/putty.rsa2 \
>> $OBJ/authorized_keys_$USER
# Convert rsa2 host key to PuTTY format
@@ -634,8 +677,6 @@ if test "$REGRESS_INTEROP_PUTTY" = "yes" ; then
PUTTYDIR=${OBJ}/.putty
export PUTTYDIR
-
- REGRESS_INTEROP_PUTTY=yes
fi
# create a proxy version of the client config
diff --git a/regress/unittests/Makefile b/regress/unittests/Makefile
index 4e56e1104..4d26b7477 100644
--- a/regress/unittests/Makefile
+++ b/regress/unittests/Makefile
@@ -1,7 +1,7 @@
-# $OpenBSD: Makefile,v 1.11 2019/04/28 22:53:26 dtucker Exp $
+# $OpenBSD: Makefile,v 1.12 2020/06/19 04:34:21 djm Exp $
REGRESS_FAIL_EARLY?= yes
SUBDIR= test_helper sshbuf sshkey bitmap kex hostkeys utf8 match conversion
-SUBDIR+=authopt misc
+SUBDIR+=authopt misc sshsig
.include <bsd.subdir.mk>
diff --git a/regress/unittests/authopt/Makefile b/regress/unittests/authopt/Makefile
index e8edc7b5f..71a7be5bd 100644
--- a/regress/unittests/authopt/Makefile
+++ b/regress/unittests/authopt/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.5 2020/04/06 09:43:55 dtucker Exp $
+# $OpenBSD: Makefile,v 1.6 2021/01/09 12:24:30 dtucker Exp $
PROG=test_authopt
SRCS=tests.c
@@ -10,7 +10,7 @@ SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c
SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c
SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c
-SRCS+=addrmatch.c bitmap.c
+SRCS+=addr.c addrmatch.c bitmap.c
SRCS+=ed25519.c hash.c ge25519.c fe25519.c sc25519.c verify.c
SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c
SRCS+=ssh-ed25519-sk.c sk-usbhid.c
diff --git a/regress/unittests/authopt/tests.c b/regress/unittests/authopt/tests.c
index 0e8aacb91..9873c09c6 100644
--- a/regress/unittests/authopt/tests.c
+++ b/regress/unittests/authopt/tests.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tests.c,v 1.1 2018/03/03 03:16:17 djm Exp $ */
+/* $OpenBSD: tests.c,v 1.2 2021/07/24 01:54:23 djm Exp $ */
/*
* Regress test for keys options functions.
@@ -6,14 +6,18 @@
* Placed in the public domain
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
+#ifdef HAVE_STDINT_H
#include <stdint.h>
+#endif
#include <stdlib.h>
#include <string.h>
-#include "test_helper.h"
+#include "../test_helper/test_helper.h"
#include "sshkey.h"
#include "authfile.h"
@@ -268,6 +272,8 @@ test_authkeys_parse(void)
} while (0)
ARRAY_TEST("environment", "environment=\"foo=1\",environment=\"bar=2\"",
env, nenv, "foo=1,bar=2");
+ ARRAY_TEST("environment", "environment=\"foo=1\",environment=\"foo=2\"",
+ env, nenv, "foo=1");
ARRAY_TEST("permitopen", "permitopen=\"foo:123\",permitopen=\"bar:*\"",
permitopen, npermitopen, "foo:123,bar:*");
#undef ARRAY_TEST
diff --git a/regress/unittests/conversion/Makefile b/regress/unittests/conversion/Makefile
index 8b2a09cc3..5793c4934 100644
--- a/regress/unittests/conversion/Makefile
+++ b/regress/unittests/conversion/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.2 2017/12/21 00:41:22 djm Exp $
+# $OpenBSD: Makefile,v 1.4 2021/01/09 12:24:30 dtucker Exp $
PROG=test_conversion
SRCS=tests.c
@@ -6,6 +6,7 @@ SRCS=tests.c
# From usr.bin/ssh
SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
SRCS+=atomicio.c misc.c xmalloc.c log.c uidswap.c cleanup.c fatal.c ssherr.c
+SRCS+=match.c addr.c addrmatch.c
REGRESS_TARGETS=run-regress-${PROG}
diff --git a/regress/unittests/conversion/tests.c b/regress/unittests/conversion/tests.c
index ae1154d42..bbdc5f5a7 100644
--- a/regress/unittests/conversion/tests.c
+++ b/regress/unittests/conversion/tests.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tests.c,v 1.2 2019/06/14 04:03:48 djm Exp $ */
+/* $OpenBSD: tests.c,v 1.3 2021/01/18 11:43:34 dtucker Exp $ */
/*
* Regress test for conversions
*
@@ -26,28 +26,28 @@ tests(void)
char buf[1024];
TEST_START("conversion_convtime");
- ASSERT_LONG_EQ(convtime("0"), 0);
- ASSERT_LONG_EQ(convtime("1"), 1);
- ASSERT_LONG_EQ(convtime("1S"), 1);
+ ASSERT_INT_EQ(convtime("0"), 0);
+ ASSERT_INT_EQ(convtime("1"), 1);
+ ASSERT_INT_EQ(convtime("1S"), 1);
/* from the examples in the comment above the function */
- ASSERT_LONG_EQ(convtime("90m"), 5400);
- ASSERT_LONG_EQ(convtime("1h30m"), 5400);
- ASSERT_LONG_EQ(convtime("2d"), 172800);
- ASSERT_LONG_EQ(convtime("1w"), 604800);
+ ASSERT_INT_EQ(convtime("90m"), 5400);
+ ASSERT_INT_EQ(convtime("1h30m"), 5400);
+ ASSERT_INT_EQ(convtime("2d"), 172800);
+ ASSERT_INT_EQ(convtime("1w"), 604800);
/* negative time is not allowed */
- ASSERT_LONG_EQ(convtime("-7"), -1);
- ASSERT_LONG_EQ(convtime("-9d"), -1);
+ ASSERT_INT_EQ(convtime("-7"), -1);
+ ASSERT_INT_EQ(convtime("-9d"), -1);
/* overflow */
- snprintf(buf, sizeof buf, "%llu", (unsigned long long)LONG_MAX);
- ASSERT_LONG_EQ(convtime(buf), -1);
- snprintf(buf, sizeof buf, "%llu", (unsigned long long)LONG_MAX + 1);
- ASSERT_LONG_EQ(convtime(buf), -1);
+ snprintf(buf, sizeof buf, "%llu", (unsigned long long)INT_MAX);
+ ASSERT_INT_EQ(convtime(buf), INT_MAX);
+ snprintf(buf, sizeof buf, "%llu", (unsigned long long)INT_MAX + 1);
+ ASSERT_INT_EQ(convtime(buf), -1);
/* overflow with multiplier */
- snprintf(buf, sizeof buf, "%lluM", (unsigned long long)LONG_MAX/60 + 1);
- ASSERT_LONG_EQ(convtime(buf), -1);
- ASSERT_LONG_EQ(convtime("1000000000000000000000w"), -1);
+ snprintf(buf, sizeof buf, "%lluM", (unsigned long long)INT_MAX/60 + 1);
+ ASSERT_INT_EQ(convtime(buf), -1);
+ ASSERT_INT_EQ(convtime("1000000000000000000000w"), -1);
TEST_DONE();
}
diff --git a/regress/unittests/hostkeys/Makefile b/regress/unittests/hostkeys/Makefile
index d841d96be..9a53423ee 100644
--- a/regress/unittests/hostkeys/Makefile
+++ b/regress/unittests/hostkeys/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.8 2020/04/06 09:43:56 dtucker Exp $
+# $OpenBSD: Makefile,v 1.9 2021/01/09 12:24:30 dtucker Exp $
PROG=test_hostkeys
SRCS=tests.c test_iterate.c
@@ -8,7 +8,7 @@ SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c
SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c
SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c
-SRCS+=addrmatch.c bitmap.c hostfile.c
+SRCS+=addr.c addrmatch.c bitmap.c hostfile.c
SRCS+=ed25519.c hash.c ge25519.c fe25519.c sc25519.c verify.c
SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c
SRCS+=ssh-ed25519-sk.c sk-usbhid.c
diff --git a/regress/unittests/hostkeys/test_iterate.c b/regress/unittests/hostkeys/test_iterate.c
index 5904121ef..a5b17d7e4 100644
--- a/regress/unittests/hostkeys/test_iterate.c
+++ b/regress/unittests/hostkeys/test_iterate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: test_iterate.c,v 1.6 2018/07/16 03:09:59 djm Exp $ */
+/* $OpenBSD: test_iterate.c,v 1.7 2020/12/21 01:31:06 djm Exp $ */
/*
* Regress test for hostfile.h hostkeys_foreach()
*
@@ -194,6 +194,7 @@ struct expected expected_full[] = {
KEY_UNSPEC, /* key type */
NULL, /* deserialised key */
NULL, /* comment */
+ 0, /* note */
} },
{ "dsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
NULL,
@@ -207,6 +208,7 @@ struct expected expected_full[] = {
KEY_DSA,
NULL, /* filled at runtime */
"DSA #1",
+ 0,
} },
{ "ecdsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
NULL,
@@ -220,6 +222,7 @@ struct expected expected_full[] = {
KEY_ECDSA,
NULL, /* filled at runtime */
"ECDSA #1",
+ 0,
} },
{ "ed25519_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
NULL,
@@ -233,6 +236,7 @@ struct expected expected_full[] = {
KEY_ED25519,
NULL, /* filled at runtime */
"ED25519 #1",
+ 0,
} },
{ "rsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
NULL,
@@ -246,6 +250,7 @@ struct expected expected_full[] = {
KEY_RSA,
NULL, /* filled at runtime */
"RSA #1",
+ 0,
} },
{ NULL, -1, -1, 0, 0, 0, 0, -1, {
NULL,
@@ -259,6 +264,7 @@ struct expected expected_full[] = {
KEY_UNSPEC,
NULL,
NULL,
+ 0,
} },
{ NULL, -1, -1, 0, 0, 0, 0, -1, {
NULL,
@@ -272,6 +278,7 @@ struct expected expected_full[] = {
KEY_UNSPEC,
NULL,
NULL,
+ 0,
} },
{ "dsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
NULL,
@@ -285,6 +292,7 @@ struct expected expected_full[] = {
KEY_DSA,
NULL, /* filled at runtime */
"DSA #2",
+ 0,
} },
{ "ecdsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
NULL,
@@ -298,6 +306,7 @@ struct expected expected_full[] = {
KEY_ECDSA,
NULL, /* filled at runtime */
"ECDSA #2",
+ 0,
} },
{ "ed25519_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
NULL,
@@ -311,6 +320,7 @@ struct expected expected_full[] = {
KEY_ED25519,
NULL, /* filled at runtime */
"ED25519 #2",
+ 0,
} },
{ "rsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
NULL,
@@ -324,6 +334,7 @@ struct expected expected_full[] = {
KEY_RSA,
NULL, /* filled at runtime */
"RSA #2",
+ 0,
} },
{ NULL, -1, -1, 0, 0, 0, 0, -1, {
NULL,
@@ -337,6 +348,7 @@ struct expected expected_full[] = {
KEY_UNSPEC,
NULL,
NULL,
+ 0,
} },
{ NULL, -1, -1, 0, 0, 0, 0, -1, {
NULL,
@@ -350,6 +362,7 @@ struct expected expected_full[] = {
KEY_UNSPEC,
NULL,
NULL,
+ 0,
} },
{ "dsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
NULL,
@@ -363,6 +376,7 @@ struct expected expected_full[] = {
KEY_DSA,
NULL, /* filled at runtime */
"DSA #3",
+ 0,
} },
{ "ecdsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
NULL,
@@ -376,6 +390,7 @@ struct expected expected_full[] = {
KEY_ECDSA,
NULL, /* filled at runtime */
"ECDSA #3",
+ 0,
} },
{ "ed25519_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
NULL,
@@ -389,6 +404,7 @@ struct expected expected_full[] = {
KEY_ED25519,
NULL, /* filled at runtime */
"ED25519 #3",
+ 0,
} },
{ "rsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
NULL,
@@ -402,6 +418,7 @@ struct expected expected_full[] = {
KEY_RSA,
NULL, /* filled at runtime */
"RSA #3",
+ 0,
} },
{ NULL, -1, -1, 0, 0, 0, 0, -1, {
NULL,
@@ -415,6 +432,7 @@ struct expected expected_full[] = {
KEY_UNSPEC,
NULL,
NULL,
+ 0,
} },
{ NULL, -1, -1, 0, 0, 0, 0, -1, {
NULL,
@@ -428,6 +446,7 @@ struct expected expected_full[] = {
KEY_UNSPEC,
NULL,
NULL,
+ 0,
} },
{ "dsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
NULL,
@@ -441,6 +460,7 @@ struct expected expected_full[] = {
KEY_DSA,
NULL, /* filled at runtime */
"DSA #5",
+ 0,
} },
{ "ecdsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
NULL,
@@ -454,6 +474,7 @@ struct expected expected_full[] = {
KEY_ECDSA,
NULL, /* filled at runtime */
"ECDSA #5",
+ 0,
} },
{ "ed25519_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
NULL,
@@ -467,6 +488,7 @@ struct expected expected_full[] = {
KEY_ED25519,
NULL, /* filled at runtime */
"ED25519 #5",
+ 0,
} },
{ "rsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
NULL,
@@ -480,6 +502,7 @@ struct expected expected_full[] = {
KEY_RSA,
NULL, /* filled at runtime */
"RSA #5",
+ 0,
} },
{ NULL, -1, -1, 0, 0, 0, 0, -1, {
NULL,
@@ -493,6 +516,7 @@ struct expected expected_full[] = {
KEY_UNSPEC,
NULL,
NULL,
+ 0,
} },
/*
* The next series have each key listed multiple times, as the
@@ -511,6 +535,7 @@ struct expected expected_full[] = {
KEY_DSA,
NULL, /* filled at runtime */
"DSA #6",
+ 0,
} },
{ "dsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
NULL,
@@ -524,6 +549,7 @@ struct expected expected_full[] = {
KEY_DSA,
NULL, /* filled at runtime */
"DSA #6",
+ 0,
} },
{ "dsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
NULL,
@@ -537,6 +563,7 @@ struct expected expected_full[] = {
KEY_DSA,
NULL, /* filled at runtime */
"DSA #6",
+ 0,
} },
{ "ecdsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
NULL,
@@ -550,6 +577,7 @@ struct expected expected_full[] = {
KEY_ECDSA,
NULL, /* filled at runtime */
"ECDSA #6",
+ 0,
} },
{ "ecdsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
NULL,
@@ -563,6 +591,7 @@ struct expected expected_full[] = {
KEY_ECDSA,
NULL, /* filled at runtime */
"ECDSA #6",
+ 0,
} },
{ "ecdsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
NULL,
@@ -576,6 +605,7 @@ struct expected expected_full[] = {
KEY_ECDSA,
NULL, /* filled at runtime */
"ECDSA #6",
+ 0,
} },
{ "ed25519_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
NULL,
@@ -589,6 +619,7 @@ struct expected expected_full[] = {
KEY_ED25519,
NULL, /* filled at runtime */
"ED25519 #6",
+ 0,
} },
{ "ed25519_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
NULL,
@@ -602,6 +633,7 @@ struct expected expected_full[] = {
KEY_ED25519,
NULL, /* filled at runtime */
"ED25519 #6",
+ 0,
} },
{ "ed25519_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
NULL,
@@ -615,6 +647,7 @@ struct expected expected_full[] = {
KEY_ED25519,
NULL, /* filled at runtime */
"ED25519 #6",
+ 0,
} },
{ "rsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
NULL,
@@ -628,6 +661,7 @@ struct expected expected_full[] = {
KEY_RSA,
NULL, /* filled at runtime */
"RSA #6",
+ 0,
} },
{ "rsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
NULL,
@@ -641,6 +675,7 @@ struct expected expected_full[] = {
KEY_RSA,
NULL, /* filled at runtime */
"RSA #6",
+ 0,
} },
{ "rsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
NULL,
@@ -654,6 +689,7 @@ struct expected expected_full[] = {
KEY_RSA,
NULL, /* filled at runtime */
"RSA #6",
+ 0,
} },
{ NULL, -1, -1, 0, 0, 0, 0, -1, {
NULL,
@@ -667,6 +703,7 @@ struct expected expected_full[] = {
KEY_UNSPEC,
NULL,
NULL,
+ 0,
} },
{ NULL, -1, -1, 0, 0, 0, 0, -1, {
NULL,
@@ -680,6 +717,7 @@ struct expected expected_full[] = {
KEY_UNSPEC,
NULL,
NULL,
+ 0,
} },
{ NULL, -1, -1, 0, 0, 0, 0, -1, {
NULL,
@@ -693,6 +731,7 @@ struct expected expected_full[] = {
KEY_UNSPEC,
NULL,
NULL,
+ 0,
} },
{ "ed25519_4.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
NULL,
@@ -706,6 +745,7 @@ struct expected expected_full[] = {
KEY_ED25519,
NULL, /* filled at runtime */
"ED25519 #4",
+ 0,
} },
{ "ecdsa_4.pub" , -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, {
NULL,
@@ -719,6 +759,7 @@ struct expected expected_full[] = {
KEY_ECDSA,
NULL, /* filled at runtime */
"ECDSA #4",
+ 0,
} },
{ "dsa_4.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, 0, 0, -1, {
NULL,
@@ -732,6 +773,7 @@ struct expected expected_full[] = {
KEY_DSA,
NULL, /* filled at runtime */
"DSA #4",
+ 0,
} },
{ NULL, -1, -1, 0, 0, 0, 0, -1, {
NULL,
@@ -745,6 +787,7 @@ struct expected expected_full[] = {
KEY_UNSPEC,
NULL,
NULL,
+ 0,
} },
{ NULL, -1, -1, 0, 0, 0, 0, -1, {
NULL,
@@ -758,6 +801,7 @@ struct expected expected_full[] = {
KEY_UNSPEC,
NULL,
NULL,
+ 0,
} },
{ NULL, -1, -1, 0, 0, 0, 0, -1, {
NULL,
@@ -771,6 +815,7 @@ struct expected expected_full[] = {
KEY_UNSPEC,
NULL,
NULL,
+ 0,
} },
{ NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
NULL,
@@ -784,6 +829,7 @@ struct expected expected_full[] = {
KEY_UNSPEC,
NULL,
NULL,
+ 0,
} },
{ NULL, -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, {
NULL,
@@ -797,6 +843,7 @@ struct expected expected_full[] = {
KEY_UNSPEC,
NULL,
NULL,
+ 0,
} },
{ NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
NULL,
@@ -810,6 +857,7 @@ struct expected expected_full[] = {
KEY_UNSPEC,
NULL,
NULL,
+ 0,
} },
{ NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
NULL,
@@ -823,6 +871,7 @@ struct expected expected_full[] = {
KEY_UNSPEC,
NULL, /* filled at runtime */
NULL,
+ 0,
} },
{ NULL, HKF_STATUS_OK, KEY_RSA, HKF_MATCH_HOST, 0, 0, 0, -1, {
NULL,
@@ -836,6 +885,7 @@ struct expected expected_full[] = {
KEY_UNSPEC,
NULL, /* filled at runtime */
NULL,
+ 0,
} },
};
@@ -853,7 +903,7 @@ test_iterate(void)
ctx.flags = HKF_WANT_PARSE_KEY;
prepare_expected(expected_full, ctx.nexpected);
ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
- check, &ctx, NULL, NULL, ctx.flags), 0);
+ check, &ctx, NULL, NULL, ctx.flags, 0), 0);
cleanup_expected(expected_full, ctx.nexpected);
TEST_DONE();
@@ -864,7 +914,7 @@ test_iterate(void)
ctx.flags = 0;
prepare_expected(expected_full, ctx.nexpected);
ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
- check, &ctx, NULL, NULL, ctx.flags), 0);
+ check, &ctx, NULL, NULL, ctx.flags, 0), 0);
cleanup_expected(expected_full, ctx.nexpected);
TEST_DONE();
@@ -876,7 +926,7 @@ test_iterate(void)
ctx.match_host_p = 1;
prepare_expected(expected_full, ctx.nexpected);
ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
- check, &ctx, "prometheus.example.com", NULL, ctx.flags), 0);
+ check, &ctx, "prometheus.example.com", NULL, ctx.flags, 0), 0);
cleanup_expected(expected_full, ctx.nexpected);
TEST_DONE();
@@ -888,7 +938,7 @@ test_iterate(void)
ctx.match_host_s = 1;
prepare_expected(expected_full, ctx.nexpected);
ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
- check, &ctx, "sisyphus.example.com", NULL, ctx.flags), 0);
+ check, &ctx, "sisyphus.example.com", NULL, ctx.flags, 0), 0);
cleanup_expected(expected_full, ctx.nexpected);
TEST_DONE();
@@ -900,7 +950,7 @@ test_iterate(void)
ctx.match_host_p = 1;
prepare_expected(expected_full, ctx.nexpected);
ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
- check, &ctx, "prometheus.example.com", NULL, ctx.flags), 0);
+ check, &ctx, "prometheus.example.com", NULL, ctx.flags, 0), 0);
cleanup_expected(expected_full, ctx.nexpected);
TEST_DONE();
@@ -912,7 +962,7 @@ test_iterate(void)
ctx.match_host_s = 1;
prepare_expected(expected_full, ctx.nexpected);
ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
- check, &ctx, "sisyphus.example.com", NULL, ctx.flags), 0);
+ check, &ctx, "sisyphus.example.com", NULL, ctx.flags, 0), 0);
cleanup_expected(expected_full, ctx.nexpected);
TEST_DONE();
@@ -923,7 +973,7 @@ test_iterate(void)
ctx.flags = 0;
prepare_expected(expected_full, ctx.nexpected);
ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
- check, &ctx, "actaeon.example.org", NULL, ctx.flags), 0);
+ check, &ctx, "actaeon.example.org", NULL, ctx.flags, 0), 0);
cleanup_expected(expected_full, ctx.nexpected);
TEST_DONE();
@@ -934,7 +984,7 @@ test_iterate(void)
ctx.flags = HKF_WANT_MATCH;
prepare_expected(expected_full, ctx.nexpected);
ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
- check, &ctx, "actaeon.example.org", NULL, ctx.flags), 0);
+ check, &ctx, "actaeon.example.org", NULL, ctx.flags, 0), 0);
cleanup_expected(expected_full, ctx.nexpected);
TEST_DONE();
@@ -946,7 +996,7 @@ test_iterate(void)
ctx.match_ipv4 = 1;
prepare_expected(expected_full, ctx.nexpected);
ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
- check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags), 0);
+ check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags, 0), 0);
cleanup_expected(expected_full, ctx.nexpected);
TEST_DONE();
@@ -958,7 +1008,8 @@ test_iterate(void)
ctx.match_ipv6 = 1;
prepare_expected(expected_full, ctx.nexpected);
ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
- check, &ctx, "tiresias.example.org", "2001:db8::1", ctx.flags), 0);
+ check, &ctx, "tiresias.example.org", "2001:db8::1",
+ ctx.flags, 0), 0);
cleanup_expected(expected_full, ctx.nexpected);
TEST_DONE();
@@ -970,7 +1021,7 @@ test_iterate(void)
ctx.match_ipv4 = 1;
prepare_expected(expected_full, ctx.nexpected);
ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
- check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags), 0);
+ check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags, 0), 0);
cleanup_expected(expected_full, ctx.nexpected);
TEST_DONE();
@@ -982,7 +1033,8 @@ test_iterate(void)
ctx.match_ipv6 = 1;
prepare_expected(expected_full, ctx.nexpected);
ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
- check, &ctx, "tiresias.example.org", "2001:db8::1", ctx.flags), 0);
+ check, &ctx, "tiresias.example.org", "2001:db8::1",
+ ctx.flags, 0), 0);
cleanup_expected(expected_full, ctx.nexpected);
TEST_DONE();
@@ -993,7 +1045,8 @@ test_iterate(void)
ctx.flags = 0;
prepare_expected(expected_full, ctx.nexpected);
ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
- check, &ctx, "tiresias.example.org", "192.168.0.1", ctx.flags), 0);
+ check, &ctx, "tiresias.example.org", "192.168.0.1",
+ ctx.flags, 0), 0);
cleanup_expected(expected_full, ctx.nexpected);
TEST_DONE();
@@ -1004,7 +1057,7 @@ test_iterate(void)
ctx.flags = HKF_WANT_MATCH;
prepare_expected(expected_full, ctx.nexpected);
ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
- check, &ctx, "tiresias.example.org", "::1", ctx.flags), 0);
+ check, &ctx, "tiresias.example.org", "::1", ctx.flags, 0), 0);
cleanup_expected(expected_full, ctx.nexpected);
TEST_DONE();
@@ -1017,7 +1070,7 @@ test_iterate(void)
ctx.match_ipv4 = 1;
prepare_expected(expected_full, ctx.nexpected);
ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
- check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags), 0);
+ check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags, 0), 0);
cleanup_expected(expected_full, ctx.nexpected);
TEST_DONE();
@@ -1031,7 +1084,7 @@ test_iterate(void)
prepare_expected(expected_full, ctx.nexpected);
ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
check, &ctx, "prometheus.example.com",
- "2001:db8::1", ctx.flags), 0);
+ "2001:db8::1", ctx.flags, 0), 0);
cleanup_expected(expected_full, ctx.nexpected);
TEST_DONE();
@@ -1044,7 +1097,7 @@ test_iterate(void)
ctx.match_ipv4 = 1;
prepare_expected(expected_full, ctx.nexpected);
ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
- check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags), 0);
+ check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags, 0), 0);
cleanup_expected(expected_full, ctx.nexpected);
TEST_DONE();
@@ -1058,7 +1111,7 @@ test_iterate(void)
prepare_expected(expected_full, ctx.nexpected);
ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
check, &ctx, "prometheus.example.com",
- "2001:db8::1", ctx.flags), 0);
+ "2001:db8::1", ctx.flags, 0), 0);
cleanup_expected(expected_full, ctx.nexpected);
TEST_DONE();
}
diff --git a/regress/unittests/kex/Makefile b/regress/unittests/kex/Makefile
index 1c5d68ce8..50b117c07 100644
--- a/regress/unittests/kex/Makefile
+++ b/regress/unittests/kex/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.10 2020/04/06 09:43:56 dtucker Exp $
+# $OpenBSD: Makefile,v 1.12 2021/01/09 12:24:30 dtucker Exp $
PROG=test_kex
SRCS=tests.c test_kex.c
@@ -8,7 +8,7 @@ SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c
SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c
SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c
-SRCS+=addrmatch.c bitmap.c packet.c dispatch.c canohost.c ssh_api.c
+SRCS+=addr.c addrmatch.c bitmap.c packet.c dispatch.c canohost.c ssh_api.c
SRCS+=compat.c ed25519.c hash.c ge25519.c fe25519.c sc25519.c verify.c
SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c
SRCS+=ssh-ed25519-sk.c sk-usbhid.c
@@ -23,8 +23,8 @@ SRCS+= kexgexs.c
SRCS+= kexc25519.c
SRCS+= smult_curve25519_ref.c
SRCS+= kexgen.c
-SRCS+= kexsntrup4591761x25519.c
-SRCS+= sntrup4591761.c
+SRCS+= kexsntrup761x25519.c
+SRCS+= sntrup761.c
SRCS+= utf8.c
SRCS+=digest-openssl.c
diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c
index 0e7cd9e07..3bd71a9f4 100644
--- a/regress/unittests/kex/test_kex.c
+++ b/regress/unittests/kex/test_kex.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: test_kex.c,v 1.4 2019/01/21 12:35:20 djm Exp $ */
+/* $OpenBSD: test_kex.c,v 1.5 2020/12/29 01:02:15 djm Exp $ */
/*
* Regress test KEX
*
@@ -152,6 +152,7 @@ do_kex_with_key(char *kex, int keytype, int bits)
#endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
server2->kex->kex[KEX_C25519_SHA256] = kex_gen_server;
+ server2->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server;
server2->kex->load_host_public_key = server->kex->load_host_public_key;
server2->kex->load_host_private_key = server->kex->load_host_private_key;
server2->kex->sign = server->kex->sign;
@@ -201,5 +202,8 @@ kex_tests(void)
do_kex("diffie-hellman-group-exchange-sha1");
do_kex("diffie-hellman-group14-sha1");
do_kex("diffie-hellman-group1-sha1");
+# ifdef USE_SNTRUP761X25519
+ do_kex("sntrup761x25519-sha512@openssh.com");
+# endif /* USE_SNTRUP761X25519 */
#endif /* WITH_OPENSSL */
}
diff --git a/regress/unittests/match/Makefile b/regress/unittests/match/Makefile
index 87e75826a..939163d30 100644
--- a/regress/unittests/match/Makefile
+++ b/regress/unittests/match/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.4 2017/12/21 03:01:49 djm Exp $
+# $OpenBSD: Makefile,v 1.5 2021/01/09 12:24:31 dtucker Exp $
PROG=test_match
SRCS=tests.c
@@ -6,7 +6,7 @@ SRCS=tests.c
# From usr.bin/ssh
SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
SRCS+=match.c misc.c log.c uidswap.c fatal.c ssherr.c addrmatch.c xmalloc.c
-SRCS+=cleanup.c atomicio.c
+SRCS+=cleanup.c atomicio.c addr.c
REGRESS_TARGETS=run-regress-${PROG}
diff --git a/regress/unittests/match/tests.c b/regress/unittests/match/tests.c
index 3d9af55f2..4fefaf4f3 100644
--- a/regress/unittests/match/tests.c
+++ b/regress/unittests/match/tests.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tests.c,v 1.5 2018/07/04 13:51:45 djm Exp $ */
+/* $OpenBSD: tests.c,v 1.7 2020/07/15 06:43:16 dtucker Exp $ */
/*
* Regress test for matching functions
*
@@ -105,7 +105,7 @@ tests(void)
#define CHECK_FILTER(string,filter,expected) \
do { \
- char *result = match_filter_blacklist((string), (filter)); \
+ char *result = match_filter_denylist((string), (filter)); \
ASSERT_STRING_EQ(result, expected); \
free(result); \
} while (0)
diff --git a/regress/unittests/misc/Makefile b/regress/unittests/misc/Makefile
index 06e954cb8..656ae44db 100644
--- a/regress/unittests/misc/Makefile
+++ b/regress/unittests/misc/Makefile
@@ -1,12 +1,27 @@
-# $OpenBSD: Makefile,v 1.1 2019/04/28 22:53:26 dtucker Exp $
+# $OpenBSD: Makefile,v 1.7 2021/05/21 03:48:07 djm Exp $
PROG=test_misc
SRCS=tests.c
+SRCS+= test_convtime.c
+SRCS+= test_expand.c
+SRCS+= test_parse.c
+SRCS+= test_argv.c
+SRCS+= test_strdelim.c
# From usr.bin/ssh/Makefile.inc
-SRCS+=sshbuf.c sshbuf-getput-basic.c ssherr.c log.c xmalloc.c misc.c
-# From usr/bin/ssh/sshd/Makefile
-SRCS+=atomicio.c cleanup.c fatal.c
+SRCS+= sshbuf.c
+SRCS+= sshbuf-getput-basic.c
+SRCS+= sshbuf-misc.c
+SRCS+= ssherr.c
+SRCS+= log.c
+SRCS+= xmalloc.c
+SRCS+= misc.c
+SRCS+= match.c
+SRCS+= addr.c
+SRCS+= addrmatch.c
+
+# From usr.bin/ssh/sshd/Makefile
+SRCS+= atomicio.c cleanup.c fatal.c
REGRESS_TARGETS=run-regress-${PROG}
diff --git a/regress/unittests/misc/test_argv.c b/regress/unittests/misc/test_argv.c
new file mode 100644
index 000000000..2cfebf2d9
--- /dev/null
+++ b/regress/unittests/misc/test_argv.c
@@ -0,0 +1,187 @@
+/* $OpenBSD: test_argv.c,v 1.3 2021/06/08 07:40:12 djm Exp $ */
+/*
+ * Regress test for misc argv handling functions.
+ *
+ * Placed in the public domain.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "../test_helper/test_helper.h"
+
+#include "log.h"
+#include "misc.h"
+
+void test_argv(void);
+
+void
+test_argv(void)
+{
+ char **av = NULL;
+ int ac = 0;
+
+#define RESET_ARGV() \
+ do { \
+ argv_free(av, ac); \
+ av = NULL; \
+ ac = -1; \
+ } while (0)
+
+ TEST_START("empty args");
+ ASSERT_INT_EQ(argv_split("", &ac, &av, 0), 0);
+ ASSERT_INT_EQ(ac, 0);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_PTR_EQ(av[0], NULL);
+ RESET_ARGV();
+ ASSERT_INT_EQ(argv_split(" ", &ac, &av, 0), 0);
+ ASSERT_INT_EQ(ac, 0);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_PTR_EQ(av[0], NULL);
+ RESET_ARGV();
+ TEST_DONE();
+
+ TEST_START("trivial args");
+ ASSERT_INT_EQ(argv_split("leamas", &ac, &av, 0), 0);
+ ASSERT_INT_EQ(ac, 1);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_STRING_EQ(av[0], "leamas");
+ ASSERT_PTR_EQ(av[1], NULL);
+ RESET_ARGV();
+ ASSERT_INT_EQ(argv_split("smiley leamas", &ac, &av, 0), 0);
+ ASSERT_INT_EQ(ac, 2);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_STRING_EQ(av[0], "smiley");
+ ASSERT_STRING_EQ(av[1], "leamas");
+ ASSERT_PTR_EQ(av[2], NULL);
+ RESET_ARGV();
+ TEST_DONE();
+
+ TEST_START("quoted");
+ ASSERT_INT_EQ(argv_split("\"smiley\"", &ac, &av, 0), 0);
+ ASSERT_INT_EQ(ac, 1);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_STRING_EQ(av[0], "smiley");
+ ASSERT_PTR_EQ(av[1], NULL);
+ RESET_ARGV();
+ ASSERT_INT_EQ(argv_split("leamas \" smiley \"", &ac, &av, 0), 0);
+ ASSERT_INT_EQ(ac, 2);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_STRING_EQ(av[0], "leamas");
+ ASSERT_STRING_EQ(av[1], " smiley ");
+ ASSERT_PTR_EQ(av[2], NULL);
+ RESET_ARGV();
+ ASSERT_INT_EQ(argv_split("\"smiley leamas\"", &ac, &av, 0), 0);
+ ASSERT_INT_EQ(ac, 1);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_STRING_EQ(av[0], "smiley leamas");
+ ASSERT_PTR_EQ(av[1], NULL);
+ RESET_ARGV();
+ ASSERT_INT_EQ(argv_split("smiley\" leamas\" liz", &ac, &av, 0), 0);
+ ASSERT_INT_EQ(ac, 2);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_STRING_EQ(av[0], "smiley leamas");
+ ASSERT_STRING_EQ(av[1], "liz");
+ ASSERT_PTR_EQ(av[2], NULL);
+ RESET_ARGV();
+ TEST_DONE();
+
+ TEST_START("escaped");
+ ASSERT_INT_EQ(argv_split("\\\"smiley\\'", &ac, &av, 0), 0);
+ ASSERT_INT_EQ(ac, 1);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_STRING_EQ(av[0], "\"smiley'");
+ ASSERT_PTR_EQ(av[1], NULL);
+ RESET_ARGV();
+ ASSERT_INT_EQ(argv_split("'\\'smiley\\\"'", &ac, &av, 0), 0);
+ ASSERT_INT_EQ(ac, 1);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_STRING_EQ(av[0], "'smiley\"");
+ ASSERT_PTR_EQ(av[1], NULL);
+ RESET_ARGV();
+ ASSERT_INT_EQ(argv_split("smiley\\'s leamas\\'", &ac, &av, 0), 0);
+ ASSERT_INT_EQ(ac, 2);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_STRING_EQ(av[0], "smiley's");
+ ASSERT_STRING_EQ(av[1], "leamas'");
+ ASSERT_PTR_EQ(av[2], NULL);
+ RESET_ARGV();
+ ASSERT_INT_EQ(argv_split("leamas\\\\smiley", &ac, &av, 0), 0);
+ ASSERT_INT_EQ(ac, 1);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_STRING_EQ(av[0], "leamas\\smiley");
+ ASSERT_PTR_EQ(av[1], NULL);
+ RESET_ARGV();
+ ASSERT_INT_EQ(argv_split("leamas\\\\ \\\\smiley", &ac, &av, 0), 0);
+ ASSERT_INT_EQ(ac, 2);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_STRING_EQ(av[0], "leamas\\");
+ ASSERT_STRING_EQ(av[1], "\\smiley");
+ ASSERT_PTR_EQ(av[2], NULL);
+ RESET_ARGV();
+ ASSERT_INT_EQ(argv_split("smiley\\ leamas", &ac, &av, 0), 0);
+ ASSERT_INT_EQ(ac, 1);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_STRING_EQ(av[0], "smiley leamas");
+ ASSERT_PTR_EQ(av[1], NULL);
+ RESET_ARGV();
+ TEST_DONE();
+
+ TEST_START("quoted escaped");
+ ASSERT_INT_EQ(argv_split("'smiley\\ leamas'", &ac, &av, 0), 0);
+ ASSERT_INT_EQ(ac, 1);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_STRING_EQ(av[0], "smiley\\ leamas");
+ ASSERT_PTR_EQ(av[1], NULL);
+ RESET_ARGV();
+ ASSERT_INT_EQ(argv_split("\"smiley\\ leamas\"", &ac, &av, 0), 0);
+ ASSERT_INT_EQ(ac, 1);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_STRING_EQ(av[0], "smiley\\ leamas");
+ ASSERT_PTR_EQ(av[1], NULL);
+ RESET_ARGV();
+ TEST_DONE();
+
+ TEST_START("comments");
+ ASSERT_INT_EQ(argv_split("# gold", &ac, &av, 0), 0);
+ ASSERT_INT_EQ(ac, 2);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_STRING_EQ(av[0], "#");
+ ASSERT_STRING_EQ(av[1], "gold");
+ ASSERT_PTR_EQ(av[2], NULL);
+ RESET_ARGV();
+ ASSERT_INT_EQ(argv_split("# gold", &ac, &av, 1), 0);
+ ASSERT_INT_EQ(ac, 0);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_PTR_EQ(av[0], NULL);
+ RESET_ARGV();
+ ASSERT_INT_EQ(argv_split("leamas#gold", &ac, &av, 1), 0);
+ ASSERT_INT_EQ(ac, 1);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_STRING_EQ(av[0], "leamas#gold");
+ ASSERT_PTR_EQ(av[1], NULL);
+ RESET_ARGV();
+ ASSERT_INT_EQ(argv_split("\"leamas # gold\"", &ac, &av, 1), 0);
+ ASSERT_INT_EQ(ac, 1);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_STRING_EQ(av[0], "leamas # gold");
+ ASSERT_PTR_EQ(av[1], NULL);
+ RESET_ARGV();
+ ASSERT_INT_EQ(argv_split("\"leamas\"#gold", &ac, &av, 1), 0);
+ ASSERT_INT_EQ(ac, 1);
+ ASSERT_PTR_NE(av, NULL);
+ ASSERT_STRING_EQ(av[0], "leamas#gold");
+ ASSERT_PTR_EQ(av[1], NULL);
+ RESET_ARGV();
+ TEST_DONE();
+
+ /* XXX test char *argv_assemble(int argc, char **argv) */
+}
diff --git a/regress/unittests/misc/test_convtime.c b/regress/unittests/misc/test_convtime.c
new file mode 100644
index 000000000..8f9be89ff
--- /dev/null
+++ b/regress/unittests/misc/test_convtime.c
@@ -0,0 +1,59 @@
+/* $OpenBSD: test_convtime.c,v 1.1 2021/03/19 03:25:01 djm Exp $ */
+/*
+ * Regress test for misc time conversion functions.
+ *
+ * Placed in the public domain.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "../test_helper/test_helper.h"
+
+#include "log.h"
+#include "misc.h"
+
+void test_convtime(void);
+
+void
+test_convtime(void)
+{
+ char buf[1024];
+
+ TEST_START("misc_convtime");
+ ASSERT_INT_EQ(convtime("0"), 0);
+ ASSERT_INT_EQ(convtime("1"), 1);
+ ASSERT_INT_EQ(convtime("2s"), 2);
+ ASSERT_INT_EQ(convtime("3m"), 180);
+ ASSERT_INT_EQ(convtime("1m30"), 90);
+ ASSERT_INT_EQ(convtime("1m30s"), 90);
+ ASSERT_INT_EQ(convtime("1h1s"), 3601);
+ ASSERT_INT_EQ(convtime("1h30m"), 90 * 60);
+ ASSERT_INT_EQ(convtime("1d"), 24 * 60 * 60);
+ ASSERT_INT_EQ(convtime("1w"), 7 * 24 * 60 * 60);
+ ASSERT_INT_EQ(convtime("1w2d3h4m5"), 788645);
+ ASSERT_INT_EQ(convtime("1w2d3h4m5s"), 788645);
+ /* any negative number or error returns -1 */
+ ASSERT_INT_EQ(convtime("-1"), -1);
+ ASSERT_INT_EQ(convtime(""), -1);
+ ASSERT_INT_EQ(convtime("trout"), -1);
+ ASSERT_INT_EQ(convtime("-77"), -1);
+ /* boundary conditions */
+ snprintf(buf, sizeof buf, "%llu", (long long unsigned)INT_MAX);
+ ASSERT_INT_EQ(convtime(buf), INT_MAX);
+ snprintf(buf, sizeof buf, "%llu", (long long unsigned)INT_MAX + 1);
+ ASSERT_INT_EQ(convtime(buf), -1);
+ ASSERT_INT_EQ(convtime("3550w5d3h14m7s"), 2147483647);
+#if INT_MAX == 2147483647
+ ASSERT_INT_EQ(convtime("3550w5d3h14m8s"), -1);
+#endif
+ TEST_DONE();
+}
diff --git a/regress/unittests/misc/test_expand.c b/regress/unittests/misc/test_expand.c
new file mode 100644
index 000000000..513c69bce
--- /dev/null
+++ b/regress/unittests/misc/test_expand.c
@@ -0,0 +1,90 @@
+/* $OpenBSD: test_expand.c,v 1.2 2021/04/06 09:07:33 dtucker Exp $ */
+/*
+ * Regress test for misc string expansion functions.
+ *
+ * Placed in the public domain.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "../test_helper/test_helper.h"
+
+#include "log.h"
+#include "misc.h"
+
+void test_expand(void);
+
+void
+test_expand(void)
+{
+ int parseerr;
+ char *ret;
+
+ TEST_START("dollar_expand");
+ ASSERT_INT_EQ(setenv("FOO", "bar", 1), 0);
+ ASSERT_INT_EQ(setenv("BAR", "baz", 1), 0);
+ (void)unsetenv("BAZ");
+#define ASSERT_DOLLAR_EQ(x, y) do { \
+ char *str = dollar_expand(NULL, (x)); \
+ ASSERT_STRING_EQ(str, (y)); \
+ free(str); \
+} while(0)
+ ASSERT_DOLLAR_EQ("${FOO}", "bar");
+ ASSERT_DOLLAR_EQ(" ${FOO}", " bar");
+ ASSERT_DOLLAR_EQ("${FOO} ", "bar ");
+ ASSERT_DOLLAR_EQ(" ${FOO} ", " bar ");
+ ASSERT_DOLLAR_EQ("${FOO}${BAR}", "barbaz");
+ ASSERT_DOLLAR_EQ(" ${FOO} ${BAR}", " bar baz");
+ ASSERT_DOLLAR_EQ("${FOO}${BAR} ", "barbaz ");
+ ASSERT_DOLLAR_EQ(" ${FOO} ${BAR} ", " bar baz ");
+ ASSERT_DOLLAR_EQ("$", "$");
+ ASSERT_DOLLAR_EQ(" $", " $");
+ ASSERT_DOLLAR_EQ("$ ", "$ ");
+
+ /* suppress error messages for error handing tests */
+ log_init("test_misc", SYSLOG_LEVEL_QUIET, SYSLOG_FACILITY_AUTH, 1);
+ /* error checking, non existent variable */
+ ret = dollar_expand(&parseerr, "a${BAZ}");
+ ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 0);
+ ret = dollar_expand(&parseerr, "${BAZ}b");
+ ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 0);
+ ret = dollar_expand(&parseerr, "a${BAZ}b");
+ ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 0);
+ /* invalid format */
+ ret = dollar_expand(&parseerr, "${");
+ ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 1);
+ ret = dollar_expand(&parseerr, "${F");
+ ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 1);
+ ret = dollar_expand(&parseerr, "${FO");
+ ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 1);
+ /* empty variable name */
+ ret = dollar_expand(&parseerr, "${}");
+ ASSERT_PTR_EQ(ret, NULL); ASSERT_INT_EQ(parseerr, 1);
+ /* restore loglevel to default */
+ log_init("test_misc", SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 1);
+ TEST_DONE();
+
+ TEST_START("percent_expand");
+ ASSERT_STRING_EQ(percent_expand("%%", "%h", "foo", NULL), "%");
+ ASSERT_STRING_EQ(percent_expand("%h", "h", "foo", NULL), "foo");
+ ASSERT_STRING_EQ(percent_expand("%h ", "h", "foo", NULL), "foo ");
+ ASSERT_STRING_EQ(percent_expand(" %h", "h", "foo", NULL), " foo");
+ ASSERT_STRING_EQ(percent_expand(" %h ", "h", "foo", NULL), " foo ");
+ ASSERT_STRING_EQ(percent_expand(" %a%b ", "a", "foo", "b", "bar", NULL),
+ " foobar ");
+ TEST_DONE();
+
+ TEST_START("percent_dollar_expand");
+ ASSERT_STRING_EQ(percent_dollar_expand("%h${FOO}", "h", "foo", NULL),
+ "foobar");
+ TEST_DONE();
+}
diff --git a/regress/unittests/misc/test_parse.c b/regress/unittests/misc/test_parse.c
new file mode 100644
index 000000000..727ff3dea
--- /dev/null
+++ b/regress/unittests/misc/test_parse.c
@@ -0,0 +1,86 @@
+/* $OpenBSD: test_parse.c,v 1.1 2021/03/19 03:25:01 djm Exp $ */
+/*
+ * Regress test for misc user/host/URI parsing functions.
+ *
+ * Placed in the public domain.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "../test_helper/test_helper.h"
+
+#include "log.h"
+#include "misc.h"
+
+void test_parse(void);
+
+void
+test_parse(void)
+{
+ int port;
+ char *user, *host, *path;
+
+ TEST_START("misc_parse_user_host_path");
+ ASSERT_INT_EQ(parse_user_host_path("someuser@some.host:some/path",
+ &user, &host, &path), 0);
+ ASSERT_STRING_EQ(user, "someuser");
+ ASSERT_STRING_EQ(host, "some.host");
+ ASSERT_STRING_EQ(path, "some/path");
+ free(user); free(host); free(path);
+ TEST_DONE();
+
+ TEST_START("misc_parse_user_ipv4_path");
+ ASSERT_INT_EQ(parse_user_host_path("someuser@1.22.33.144:some/path",
+ &user, &host, &path), 0);
+ ASSERT_STRING_EQ(user, "someuser");
+ ASSERT_STRING_EQ(host, "1.22.33.144");
+ ASSERT_STRING_EQ(path, "some/path");
+ free(user); free(host); free(path);
+ TEST_DONE();
+
+ TEST_START("misc_parse_user_[ipv4]_path");
+ ASSERT_INT_EQ(parse_user_host_path("someuser@[1.22.33.144]:some/path",
+ &user, &host, &path), 0);
+ ASSERT_STRING_EQ(user, "someuser");
+ ASSERT_STRING_EQ(host, "1.22.33.144");
+ ASSERT_STRING_EQ(path, "some/path");
+ free(user); free(host); free(path);
+ TEST_DONE();
+
+ TEST_START("misc_parse_user_[ipv4]_nopath");
+ ASSERT_INT_EQ(parse_user_host_path("someuser@[1.22.33.144]:",
+ &user, &host, &path), 0);
+ ASSERT_STRING_EQ(user, "someuser");
+ ASSERT_STRING_EQ(host, "1.22.33.144");
+ ASSERT_STRING_EQ(path, ".");
+ free(user); free(host); free(path);
+ TEST_DONE();
+
+ TEST_START("misc_parse_user_ipv6_path");
+ ASSERT_INT_EQ(parse_user_host_path("someuser@[::1]:some/path",
+ &user, &host, &path), 0);
+ ASSERT_STRING_EQ(user, "someuser");
+ ASSERT_STRING_EQ(host, "::1");
+ ASSERT_STRING_EQ(path, "some/path");
+ free(user); free(host); free(path);
+ TEST_DONE();
+
+ TEST_START("misc_parse_uri");
+ ASSERT_INT_EQ(parse_uri("ssh", "ssh://someuser@some.host:22/some/path",
+ &user, &host, &port, &path), 0);
+ ASSERT_STRING_EQ(user, "someuser");
+ ASSERT_STRING_EQ(host, "some.host");
+ ASSERT_INT_EQ(port, 22);
+ ASSERT_STRING_EQ(path, "some/path");
+ free(user); free(host); free(path);
+ TEST_DONE();
+}
diff --git a/regress/unittests/misc/test_strdelim.c b/regress/unittests/misc/test_strdelim.c
new file mode 100644
index 000000000..1d9133d4b
--- /dev/null
+++ b/regress/unittests/misc/test_strdelim.c
@@ -0,0 +1,202 @@
+/* $OpenBSD: test_strdelim.c,v 1.2 2021/05/21 03:59:01 djm Exp $ */
+/*
+ * Regress test for misc strdelim() and co
+ *
+ * Placed in the public domain.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "../test_helper/test_helper.h"
+
+#include "log.h"
+#include "misc.h"
+#include "xmalloc.h"
+
+void test_strdelim(void);
+
+void
+test_strdelim(void)
+{
+ char *orig, *str, *cp;
+
+#define START_STRING(x) orig = str = xstrdup(x)
+#define DONE_STRING() free(orig)
+
+ TEST_START("empty");
+ START_STRING("");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, ""); /* XXX arguable */
+ cp = strdelim(&str);
+ ASSERT_PTR_EQ(cp, NULL);
+ DONE_STRING();
+ TEST_DONE();
+
+ TEST_START("whitespace");
+ START_STRING(" ");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, ""); /* XXX better as NULL */
+ ASSERT_STRING_EQ(str, "");
+ DONE_STRING();
+ TEST_DONE();
+
+ TEST_START("trivial");
+ START_STRING("blob");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob");
+ cp = strdelim(&str);
+ ASSERT_PTR_EQ(cp, NULL);
+ ASSERT_PTR_EQ(str, NULL);
+ DONE_STRING();
+ TEST_DONE();
+
+ TEST_START("trivial whitespace");
+ START_STRING("blob ");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob");
+ ASSERT_STRING_EQ(str, "");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, ""); /* XXX better as NULL */
+ ASSERT_PTR_EQ(str, NULL);
+ DONE_STRING();
+ TEST_DONE();
+
+ TEST_START("multi");
+ START_STRING("blob1 blob2");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob1");
+ ASSERT_STRING_EQ(str, "blob2");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob2");
+ ASSERT_PTR_EQ(str, NULL);
+ cp = strdelim(&str);
+ ASSERT_PTR_EQ(cp, NULL);
+ DONE_STRING();
+ TEST_DONE();
+
+ TEST_START("multi whitespace");
+ START_STRING("blob1 blob2 ");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob1");
+ ASSERT_STRING_EQ(str, "blob2 ");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob2");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, ""); /* XXX better as NULL */
+ ASSERT_PTR_EQ(str, NULL);
+ DONE_STRING();
+ TEST_DONE();
+
+ TEST_START("multi equals");
+ START_STRING("blob1=blob2");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob1");
+ ASSERT_STRING_EQ(str, "blob2");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob2");
+ ASSERT_PTR_EQ(str, NULL);
+ cp = strdelim(&str);
+ ASSERT_PTR_EQ(cp, NULL);
+ DONE_STRING();
+ TEST_DONE();
+
+ TEST_START("multi too many equals");
+ START_STRING("blob1==blob2");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob1"); /* XXX better returning NULL early */
+ ASSERT_STRING_EQ(str, "=blob2");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "");
+ ASSERT_STRING_EQ(str, "blob2");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob2"); /* XXX should (but can't) reject */
+ ASSERT_PTR_EQ(str, NULL);
+ DONE_STRING();
+ TEST_DONE();
+
+ TEST_START("multi equals strdelimw");
+ START_STRING("blob1=blob2");
+ cp = strdelimw(&str);
+ ASSERT_STRING_EQ(cp, "blob1=blob2");
+ ASSERT_PTR_EQ(str, NULL);
+ cp = strdelimw(&str);
+ ASSERT_PTR_EQ(cp, NULL);
+ DONE_STRING();
+ TEST_DONE();
+
+ TEST_START("quoted");
+ START_STRING("\"blob\"");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, ""); /* XXX better as NULL */
+ ASSERT_PTR_EQ(str, NULL);
+ DONE_STRING();
+ TEST_DONE();
+
+ TEST_START("quoted multi");
+ START_STRING("\"blob1\" blob2");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob1");
+ ASSERT_STRING_EQ(str, "blob2");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob2");
+ ASSERT_PTR_EQ(str, NULL);
+ cp = strdelim(&str);
+ ASSERT_PTR_EQ(cp, NULL);
+ DONE_STRING();
+ TEST_DONE();
+
+ TEST_START("quoted multi reverse");
+ START_STRING("blob1 \"blob2\"");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob1");
+ ASSERT_STRING_EQ(str, "\"blob2\"");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob2");
+ ASSERT_STRING_EQ(str, "");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, ""); /* XXX better as NULL */
+ ASSERT_PTR_EQ(str, NULL);
+ DONE_STRING();
+ TEST_DONE();
+
+ TEST_START("quoted multi middle");
+ START_STRING("blob1 \"blob2\" blob3");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob1");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob2");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob3");
+ cp = strdelim(&str);
+ ASSERT_PTR_EQ(cp, NULL);
+ DONE_STRING();
+ TEST_DONE();
+
+ TEST_START("badquote");
+ START_STRING("\"blob");
+ cp = strdelim(&str);
+ ASSERT_PTR_EQ(cp, NULL);
+ DONE_STRING();
+ TEST_DONE();
+
+ TEST_START("oops quote");
+ START_STRING("\"blob\\\"");
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "blob\\"); /* XXX wrong */
+ cp = strdelim(&str);
+ ASSERT_STRING_EQ(cp, "");
+ DONE_STRING();
+ TEST_DONE();
+
+}
diff --git a/regress/unittests/misc/tests.c b/regress/unittests/misc/tests.c
index ed775ebbd..b0b7cd433 100644
--- a/regress/unittests/misc/tests.c
+++ b/regress/unittests/misc/tests.c
@@ -1,79 +1,38 @@
-/* $OpenBSD: tests.c,v 1.1 2019/04/28 22:53:26 dtucker Exp $ */
+/* $OpenBSD: tests.c,v 1.7 2021/05/21 03:48:07 djm Exp $ */
/*
* Regress test for misc helper functions.
*
* Placed in the public domain.
*/
+#include "includes.h"
+
#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
+#ifdef HAVE_STDINT_H
#include <stdint.h>
+#endif
#include <stdlib.h>
#include <string.h>
-#include "test_helper.h"
+#include "../test_helper/test_helper.h"
+#include "log.h"
#include "misc.h"
+void test_parse(void);
+void test_convtime(void);
+void test_expand(void);
+void test_argv(void);
+void test_strdelim(void);
+
void
tests(void)
{
- int port;
- char *user, *host, *path;
-
- TEST_START("misc_parse_user_host_path");
- ASSERT_INT_EQ(parse_user_host_path("someuser@some.host:some/path",
- &user, &host, &path), 0);
- ASSERT_STRING_EQ(user, "someuser");
- ASSERT_STRING_EQ(host, "some.host");
- ASSERT_STRING_EQ(path, "some/path");
- free(user); free(host); free(path);
- TEST_DONE();
-
- TEST_START("misc_parse_user_ipv4_path");
- ASSERT_INT_EQ(parse_user_host_path("someuser@1.22.33.144:some/path",
- &user, &host, &path), 0);
- ASSERT_STRING_EQ(user, "someuser");
- ASSERT_STRING_EQ(host, "1.22.33.144");
- ASSERT_STRING_EQ(path, "some/path");
- free(user); free(host); free(path);
- TEST_DONE();
-
- TEST_START("misc_parse_user_[ipv4]_path");
- ASSERT_INT_EQ(parse_user_host_path("someuser@[1.22.33.144]:some/path",
- &user, &host, &path), 0);
- ASSERT_STRING_EQ(user, "someuser");
- ASSERT_STRING_EQ(host, "1.22.33.144");
- ASSERT_STRING_EQ(path, "some/path");
- free(user); free(host); free(path);
- TEST_DONE();
-
- TEST_START("misc_parse_user_[ipv4]_nopath");
- ASSERT_INT_EQ(parse_user_host_path("someuser@[1.22.33.144]:",
- &user, &host, &path), 0);
- ASSERT_STRING_EQ(user, "someuser");
- ASSERT_STRING_EQ(host, "1.22.33.144");
- ASSERT_STRING_EQ(path, ".");
- free(user); free(host); free(path);
- TEST_DONE();
-
- TEST_START("misc_parse_user_ipv6_path");
- ASSERT_INT_EQ(parse_user_host_path("someuser@[::1]:some/path",
- &user, &host, &path), 0);
- ASSERT_STRING_EQ(user, "someuser");
- ASSERT_STRING_EQ(host, "::1");
- ASSERT_STRING_EQ(path, "some/path");
- free(user); free(host); free(path);
- TEST_DONE();
-
- TEST_START("misc_parse_uri");
- ASSERT_INT_EQ(parse_uri("ssh", "ssh://someuser@some.host:22/some/path",
- &user, &host, &port, &path), 0);
- ASSERT_STRING_EQ(user, "someuser");
- ASSERT_STRING_EQ(host, "some.host");
- ASSERT_INT_EQ(port, 22);
- ASSERT_STRING_EQ(path, "some/path");
- free(user); free(host); free(path);
- TEST_DONE();
+ test_parse();
+ test_convtime();
+ test_expand();
+ test_argv();
+ test_strdelim();
}
diff --git a/regress/unittests/sshbuf/Makefile b/regress/unittests/sshbuf/Makefile
index 5f6c4426a..a8ddfaf7e 100644
--- a/regress/unittests/sshbuf/Makefile
+++ b/regress/unittests/sshbuf/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.8 2020/01/26 00:09:50 djm Exp $
+# $OpenBSD: Makefile,v 1.10 2021/01/09 12:24:31 dtucker Exp $
# $OpenBSD: Makefile,v 1.8 2020/01/26 00:09:50 djm Exp $
@@ -15,6 +15,7 @@ SRCS+=test_sshbuf_fixed.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 misc.c xmalloc.c log.c fatal.c ssherr.c cleanup.c
+SRCS+=match.c addr.c addrmatch.c
run-regress-${PROG}: ${PROG}
env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS}
diff --git a/regress/unittests/sshkey/Makefile b/regress/unittests/sshkey/Makefile
index 29c9b3ba7..d4a892375 100644
--- a/regress/unittests/sshkey/Makefile
+++ b/regress/unittests/sshkey/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.10 2020/04/06 09:43:56 dtucker Exp $
+# $OpenBSD: Makefile,v 1.11 2021/01/09 12:24:31 dtucker Exp $
PROG=test_sshkey
SRCS=tests.c test_sshkey.c test_file.c test_fuzz.c common.c
@@ -8,7 +8,7 @@ SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c
SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c
SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c
-SRCS+=addrmatch.c bitmap.c
+SRCS+=addr.c addrmatch.c bitmap.c
SRCS+=ed25519.c hash.c ge25519.c fe25519.c sc25519.c verify.c
SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c
SRCS+=ssh-ed25519-sk.c sk-usbhid.c
diff --git a/regress/unittests/sshkey/mktestdata.sh b/regress/unittests/sshkey/mktestdata.sh
index 8efe6dd03..fcd78e990 100755
--- a/regress/unittests/sshkey/mktestdata.sh
+++ b/regress/unittests/sshkey/mktestdata.sh
@@ -1,5 +1,5 @@
#!/bin/sh
-# $OpenBSD: mktestdata.sh,v 1.10 2020/05/01 04:03:14 djm Exp $
+# $OpenBSD: mktestdata.sh,v 1.11 2020/06/19 03:48:49 djm Exp $
PW=mekmitasdigoat
@@ -70,6 +70,15 @@ set -ex
cd testdata
+if [ -f ../../../misc/sk-dummy/sk-dummy.so ] ; then
+ SK_DUMMY=../../../misc/sk-dummy/sk-dummy.so
+elif [ -f ../../../misc/sk-dummy/obj/sk-dummy.so ] ; then
+ SK_DUMMY=../../../misc/sk-dummy/obj/sk-dummy.so
+else
+ echo "Can't find sk-dummy.so" 1>&2
+ exit 1
+fi
+
rm -f rsa_1 dsa_1 ecdsa_1 ed25519_1
rm -f rsa_2 dsa_2 ecdsa_2 ed25519_2
rm -f rsa_n dsa_n ecdsa_n # new-format keys
@@ -81,11 +90,20 @@ ssh-keygen -t rsa -b 1024 -C "RSA test key #1" -N "" -f rsa_1 -m PEM
ssh-keygen -t dsa -b 1024 -C "DSA test key #1" -N "" -f dsa_1 -m PEM
ssh-keygen -t ecdsa -b 256 -C "ECDSA test key #1" -N "" -f ecdsa_1 -m PEM
ssh-keygen -t ed25519 -C "ED25519 test key #1" -N "" -f ed25519_1
+ssh-keygen -w "$SK_DUMMY" -t ecdsa-sk -C "ECDSA-SK test key #1" \
+ -N "" -f ecdsa_sk1
+ssh-keygen -w "$SK_DUMMY" -t ed25519-sk -C "ED25519-SK test key #1" \
+ -N "" -f ed25519_sk1
+
ssh-keygen -t rsa -b 2048 -C "RSA test key #2" -N "" -f rsa_2 -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 #1" -N "" -f ed25519_2
+ssh-keygen -t ed25519 -C "ED25519 test key #2" -N "" -f ed25519_2
+ssh-keygen -w "$SK_DUMMY" -t ecdsa-sk -C "ECDSA-SK test key #2" \
+ -N "" -f ecdsa_sk2
+ssh-keygen -w "$SK_DUMMY" -t ed25519-sk -C "ED25519-SK test key #2" \
+ -N "" -f ed25519_sk2
cp rsa_1 rsa_n
cp dsa_1 dsa_n
@@ -99,6 +117,8 @@ 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
@@ -107,6 +127,8 @@ 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"
@@ -117,7 +139,7 @@ dsa_params dsa_1 dsa_1.param
dsa_params dsa_1 dsa_1.param
ecdsa_params ecdsa_1 ecdsa_1.param
ecdsa_params ecdsa_2 ecdsa_2.param
-# XXX ed25519 params
+# XXX ed25519, *sk params
ssh-keygen -s rsa_2 -I hugo -n user1,user2 \
-Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \
@@ -131,6 +153,13 @@ ssh-keygen -s rsa_2 -I hugo -n user1,user2 \
ssh-keygen -s rsa_2 -I hugo -n user1,user2 \
-Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \
-V 19990101:20110101 -z 4 ed25519_1.pub
+ssh-keygen -s rsa_2 -I hugo -n user1,user2 \
+ -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \
+ -V 19990101:20110101 -z 4 ecdsa_sk1.pub
+ssh-keygen -s rsa_2 -I hugo -n user1,user2 \
+ -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \
+ -V 19990101:20110101 -z 4 ed25519_sk1.pub
+
# Make a few RSA variant signature too.
cp rsa_1 rsa_1_sha1
@@ -152,30 +181,42 @@ ssh-keygen -s ecdsa_1 -I julius -n host1,host2 -h \
-V 19990101:20110101 -z 7 ecdsa_1.pub
ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \
-V 19990101:20110101 -z 8 ed25519_1.pub
+ssh-keygen -s ecdsa_1 -I julius -n host1,host2 -h \
+ -V 19990101:20110101 -z 7 ecdsa_sk1.pub
+ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \
+ -V 19990101:20110101 -z 8 ed25519_sk1.pub
ssh-keygen -lf rsa_1 | awk '{print $2}' > rsa_1.fp
ssh-keygen -lf dsa_1 | awk '{print $2}' > dsa_1.fp
ssh-keygen -lf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp
ssh-keygen -lf ed25519_1 | awk '{print $2}' > ed25519_1.fp
+ssh-keygen -lf ecdsa_sk1 | awk '{print $2}' > ecdsa_sk1.fp
+ssh-keygen -lf ed25519_sk1 | awk '{print $2}' > ed25519_sk1.fp
ssh-keygen -lf rsa_2 | awk '{print $2}' > rsa_2.fp
ssh-keygen -lf dsa_2 | awk '{print $2}' > dsa_2.fp
ssh-keygen -lf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp
ssh-keygen -lf ed25519_2 | awk '{print $2}' > ed25519_2.fp
+ssh-keygen -lf ecdsa_sk2 | awk '{print $2}' > ecdsa_sk2.fp
+ssh-keygen -lf ed25519_sk2 | awk '{print $2}' > ed25519_sk2.fp
+ssh-keygen -lf rsa_1-cert.pub | awk '{print $2}' > rsa_1-cert.fp
ssh-keygen -lf dsa_1-cert.pub | awk '{print $2}' > dsa_1-cert.fp
ssh-keygen -lf ecdsa_1-cert.pub | awk '{print $2}' > ecdsa_1-cert.fp
ssh-keygen -lf ed25519_1-cert.pub | awk '{print $2}' > ed25519_1-cert.fp
-ssh-keygen -lf rsa_1-cert.pub | awk '{print $2}' > rsa_1-cert.fp
+ssh-keygen -lf ecdsa_sk1-cert.pub | awk '{print $2}' > ecdsa_sk1-cert.fp
+ssh-keygen -lf ed25519_sk1-cert.pub | awk '{print $2}' > ed25519_sk1-cert.fp
ssh-keygen -Bf rsa_1 | awk '{print $2}' > rsa_1.fp.bb
ssh-keygen -Bf dsa_1 | awk '{print $2}' > dsa_1.fp.bb
ssh-keygen -Bf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp.bb
ssh-keygen -Bf ed25519_1 | awk '{print $2}' > ed25519_1.fp.bb
+ssh-keygen -Bf ecdsa_sk1 | awk '{print $2}' > ecdsa_sk1.fp.bb
+ssh-keygen -Bf ed25519_sk1 | awk '{print $2}' > ed25519_sk1.fp.bb
ssh-keygen -Bf rsa_2 | awk '{print $2}' > rsa_2.fp.bb
ssh-keygen -Bf dsa_2 | awk '{print $2}' > dsa_2.fp.bb
ssh-keygen -Bf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp.bb
ssh-keygen -Bf ed25519_2 | awk '{print $2}' > ed25519_2.fp.bb
-
-# XXX Extend ssh-keygen to do detached signatures (better to test/fuzz against)
+ssh-keygen -Bf ecdsa_sk2 | awk '{print $2}' > ecdsa_sk2.fp.bb
+ssh-keygen -Bf ed25519_sk2 | awk '{print $2}' > ed25519_sk2.fp.bb
echo "$PW" > pw
diff --git a/regress/unittests/sshkey/test_file.c b/regress/unittests/sshkey/test_file.c
index 55627bc12..7d767336e 100644
--- a/regress/unittests/sshkey/test_file.c
+++ b/regress/unittests/sshkey/test_file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: test_file.c,v 1.8 2018/09/13 09:03:20 djm Exp $ */
+/* $OpenBSD: test_file.c,v 1.9 2020/06/19 03:48:49 djm Exp $ */
/*
* Regress test for sshkey.h key management API
*
@@ -422,6 +422,137 @@ sshkey_file_tests(void)
sshkey_free(k1);
+#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
+ TEST_START("parse ECDSA-SK from private");
+ buf = load_file("ecdsa_sk1");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(k1, NULL);
+ ASSERT_INT_EQ(k1->type, KEY_ECDSA_SK);
+ TEST_DONE();
+
+ TEST_START("parse ECDSA-SK from private w/ passphrase");
+ buf = load_file("ecdsa_sk1_pw");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
+ (const char *)sshbuf_ptr(pw), &k2, NULL), 0);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("load ECDSA-SK from public");
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("ecdsa_sk1.pub"), &k2,
+ NULL), 0);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("load ECDSA-SK cert");
+ ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_sk1"), &k2), 0);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(k2->type, KEY_ECDSA_SK_CERT);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 0);
+ ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1);
+ TEST_DONE();
+
+ TEST_START("ECDSA-SK key hex fingerprint");
+ buf = load_text_file("ecdsa_sk1.fp");
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64);
+ ASSERT_PTR_NE(cp, NULL);
+ ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
+ sshbuf_free(buf);
+ free(cp);
+ TEST_DONE();
+
+ TEST_START("ECDSA-SK cert hex fingerprint");
+ buf = load_text_file("ecdsa_sk1-cert.fp");
+ cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64);
+ ASSERT_PTR_NE(cp, NULL);
+ ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
+ sshbuf_free(buf);
+ free(cp);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("ECDSA-SK key bubblebabble fingerprint");
+ buf = load_text_file("ecdsa_sk1.fp.bb");
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE);
+ ASSERT_PTR_NE(cp, NULL);
+ ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
+ sshbuf_free(buf);
+ free(cp);
+ TEST_DONE();
+
+ sshkey_free(k1);
+#endif
+
+ TEST_START("parse Ed25519-SK from private");
+ buf = load_file("ed25519_sk1");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(k1, NULL);
+ ASSERT_INT_EQ(k1->type, KEY_ED25519_SK);
+ /* XXX check key contents */
+ TEST_DONE();
+
+ TEST_START("parse Ed25519-SK from private w/ passphrase");
+ buf = load_file("ed25519_sk1_pw");
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
+ (const char *)sshbuf_ptr(pw), &k2, NULL), 0);
+ sshbuf_free(buf);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("load Ed25519-SK from public");
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_sk1.pub"),
+ &k2, NULL), 0);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("load Ed25519-SK cert");
+ ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_sk1"), &k2), 0);
+ ASSERT_PTR_NE(k2, NULL);
+ ASSERT_INT_EQ(k2->type, KEY_ED25519_SK_CERT);
+ ASSERT_INT_EQ(sshkey_equal(k1, k2), 0);
+ ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1);
+ TEST_DONE();
+
+ TEST_START("Ed25519-SK key hex fingerprint");
+ buf = load_text_file("ed25519_sk1.fp");
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA256, SSH_FP_BASE64);
+ ASSERT_PTR_NE(cp, NULL);
+ ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
+ sshbuf_free(buf);
+ free(cp);
+ TEST_DONE();
+
+ TEST_START("Ed25519-SK cert hex fingerprint");
+ buf = load_text_file("ed25519_sk1-cert.fp");
+ cp = sshkey_fingerprint(k2, SSH_DIGEST_SHA256, SSH_FP_BASE64);
+ ASSERT_PTR_NE(cp, NULL);
+ ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
+ sshbuf_free(buf);
+ free(cp);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("Ed25519-SK key bubblebabble fingerprint");
+ buf = load_text_file("ed25519_sk1.fp.bb");
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE);
+ ASSERT_PTR_NE(cp, NULL);
+ ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
+ sshbuf_free(buf);
+ free(cp);
+ TEST_DONE();
+
+ sshkey_free(k1);
+
sshbuf_free(pw);
}
diff --git a/regress/unittests/sshkey/test_fuzz.c b/regress/unittests/sshkey/test_fuzz.c
index 359811893..f111446a9 100644
--- a/regress/unittests/sshkey/test_fuzz.c
+++ b/regress/unittests/sshkey/test_fuzz.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: test_fuzz.c,v 1.11 2019/11/25 10:32:35 djm Exp $ */
+/* $OpenBSD: test_fuzz.c,v 1.12 2020/08/27 03:55:22 djm Exp $ */
/*
* Fuzz tests for key parsing
*
@@ -88,7 +88,7 @@ sig_fuzz(struct sshkey *k, const char *sig_alg)
fuzzers |= FUZZ_2_BIT_FLIP;
ASSERT_INT_EQ(sshkey_sign(k, &sig, &l, c, sizeof(c),
- sig_alg, NULL, 0), 0);
+ sig_alg, NULL, NULL, 0), 0);
ASSERT_SIZE_T_GT(l, 0);
fuzz = fuzz_begin(fuzzers, sig, l);
ASSERT_INT_EQ(sshkey_verify(k, sig, l, c, sizeof(c), NULL, 0, NULL), 0);
diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c
index 025bb9815..7dc20cc85 100644
--- a/regress/unittests/sshkey/test_sshkey.c
+++ b/regress/unittests/sshkey/test_sshkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: test_sshkey.c,v 1.20 2019/11/25 10:32:35 djm Exp $ */
+/* $OpenBSD: test_sshkey.c,v 1.21 2020/08/27 03:55:22 djm Exp $ */
/*
* Regress test for sshkey.h key management API
*
@@ -101,7 +101,7 @@ build_cert(struct sshbuf *b, struct sshkey *k, const char *type,
ASSERT_INT_EQ(sshbuf_put_string(b, NULL, 0), 0); /* reserved */
ASSERT_INT_EQ(sshbuf_put_stringb(b, ca_buf), 0); /* signature key */
ASSERT_INT_EQ(sshkey_sign(sign_key, &sigblob, &siglen,
- sshbuf_ptr(b), sshbuf_len(b), sig_alg, NULL, 0), 0);
+ sshbuf_ptr(b), sshbuf_len(b), sig_alg, NULL, NULL, 0), 0);
ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */
free(sigblob);
@@ -120,7 +120,8 @@ signature_test(struct sshkey *k, struct sshkey *bad, const char *sig_alg,
size_t len;
u_char *sig;
- ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, sig_alg, NULL, 0), 0);
+ ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, sig_alg,
+ NULL, NULL, 0), 0);
ASSERT_SIZE_T_GT(len, 8);
ASSERT_PTR_NE(sig, NULL);
ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0);
@@ -437,7 +438,7 @@ sshkey_tests(void)
put_opt(k1->cert->extensions, "permit-X11-forwarding", NULL);
put_opt(k1->cert->extensions, "permit-agent-forwarding", NULL);
ASSERT_INT_EQ(sshkey_from_private(k2, &k1->cert->signature_key), 0);
- ASSERT_INT_EQ(sshkey_certify(k1, k2, NULL, NULL), 0);
+ ASSERT_INT_EQ(sshkey_certify(k1, k2, NULL, NULL, NULL), 0);
b = sshbuf_new();
ASSERT_PTR_NE(b, NULL);
ASSERT_INT_EQ(sshkey_putb(k1, b), 0);
diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1 b/regress/unittests/sshkey/testdata/ecdsa_sk1
new file mode 100644
index 000000000..b51fb73d6
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_sk1
@@ -0,0 +1,13 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2
+RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQRnVT5Cji1D
+Ge2+q2X0vATh6LYnODV+DJrshJorr5GnipW29RfuaDXs0WB6XBej9dOLazVRDjQrtV19Qg
+O6cfkFAAAABHNzaDoAAAGQuPdnP7j3Zz8AAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv
+cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEEZ1U+Qo4tQxntvqtl9LwE4ei2Jzg1fgya7I
+SaK6+Rp4qVtvUX7mg17NFgelwXo/XTi2s1UQ40K7VdfUIDunH5BQAAAARzc2g6AQAAAOMt
+LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJRURmVFB4YzA0alN5Zk
+Z5NlhoV1pTVlpzcnU5ZFlaSVpTOWhjeVFhcDlVT29Bb0dDQ3FHU000OQpBd0VIb1VRRFFn
+QUVaMVUrUW80dFF4bnR2cXRsOUx3RTRlaTJKemcxZmd5YTdJU2FLNitScDRxVnR2VVg3bW
+cxCjdORmdlbHdYby9YVGkyczFVUTQwSzdWZGZVSUR1bkg1QlE9PQotLS0tLUVORCBFQyBQ
+UklWQVRFIEtFWS0tLS0tCgAAAAAAAAAURUNEU0EtU0sgdGVzdCBrZXkgIzEBAgMEBQ==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.fp b/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.fp
new file mode 100644
index 000000000..d1921451d
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.fp
@@ -0,0 +1 @@
+SHA256:Go7HO0CVPYG+BSDSk9ZUJBKGSrtBExp6obTa9iqzIUo
diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.pub b/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.pub
new file mode 100644
index 000000000..9586c61a7
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_sk1-cert.pub
@@ -0,0 +1 @@
+sk-ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAK3NrLWVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgE012YoSBE9hEC2FRzblcSx784JNo2A4g611A7I75YMMAAAAIbmlzdHAyNTYAAABBBGdVPkKOLUMZ7b6rZfS8BOHotic4NX4MmuyEmiuvkaeKlbb1F+5oNezRYHpcF6P104trNVEONCu1XX1CA7px+QUAAAAEc3NoOgAAAAAAAAAHAAAAAgAAAAZqdWxpdXMAAAASAAAABWhvc3QxAAAABWhvc3QyAAAAADaLg2AAAAAATR3h4AAAAAAAAAAAAAAAAAAAAGgAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAAhuaXN0cDI1NgAAAEEEAlTtPiWUHubBeCys4Xp0QF91dYARpkyqtCnzg10HRS+ZDgkMrSUvPPG+Ge8iqtnB951MBxDq9FqDFIkhQBYXDAAAAGQAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAEkAAAAhALY+eXRJjVGnMk38Sm5S+H5CloNq757ypsoxt+WYoadtAAAAIA42/mAhUfLij1GY7wl+OFrI+icB/t4tGiEUZmhx6Foo ECDSA-SK test key #1
diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1.fp b/regress/unittests/sshkey/testdata/ecdsa_sk1.fp
new file mode 100644
index 000000000..d1921451d
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_sk1.fp
@@ -0,0 +1 @@
+SHA256:Go7HO0CVPYG+BSDSk9ZUJBKGSrtBExp6obTa9iqzIUo
diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1.fp.bb b/regress/unittests/sshkey/testdata/ecdsa_sk1.fp.bb
new file mode 100644
index 000000000..cb9f4dd0d
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_sk1.fp.bb
@@ -0,0 +1 @@
+xovem-sacac-dageg-vovoc-symyz-bozal-cibiv-cyvat-vylyn-romib-hoxax
diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1.pub b/regress/unittests/sshkey/testdata/ecdsa_sk1.pub
new file mode 100644
index 000000000..c3b21e02b
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_sk1.pub
@@ -0,0 +1 @@
+sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGdVPkKOLUMZ7b6rZfS8BOHotic4NX4MmuyEmiuvkaeKlbb1F+5oNezRYHpcF6P104trNVEONCu1XX1CA7px+QUAAAAEc3NoOg== ECDSA-SK test key #1
diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk1_pw b/regress/unittests/sshkey/testdata/ecdsa_sk1_pw
new file mode 100644
index 000000000..4fa23a738
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_sk1_pw
@@ -0,0 +1,14 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABB6vcJVx2
+cPc7yYRROup8VnAAAAEAAAAAEAAAB/AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3Bl
+bnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGdVPkKOLUMZ7b6rZfS8BOHotic4NX4MmuyEmi
+uvkaeKlbb1F+5oNezRYHpcF6P104trNVEONCu1XX1CA7px+QUAAAAEc3NoOgAAAZBrvCxe
+xFz0bvzXwaPhrUHBeNCoZy/wNKDx0kxlxUPuA+lgOvy5l3lT3yxxd0qj5PQB+NTcuz8AAE
+1f7aSWQNZSifox3COsBGoHV9C8i+glcxiBKheAZD+EBnRGjG8kbcaLhuYDW/I39qNe8lHW
+YSDjmvsT55Hy0IAtVRAXizDoXKNdFPTZisC67WyOSJ3ED7Fy4bfT4ApbvhoFTwjikZBEhy
+LOad1sbJa4eT19TsskYfQdnJf8sjAmCMOZY4ZV0FiNW5XZOp8nIal1oyULPfzTAm6oaeFN
+0ImCSU3U8h4wUQ8q/3XvBWtTKycZaoou0AwPoP0QN95Ywte7FHezNPb/n8KD7k0S6h9XAX
+UcBeCe5NHyov/0ZzA2p737hzm3w+MXGOboTQMu8WFXeGh4m7QH2o8ZJdgBhM5JF17uii+Q
+ppGoPWHf33MXwB3wxWmKZ0ua0f9AVLkQ2DfFszUoBJE/kcHRd4kj4Q4FWXeMBN0GoH8gdE
+gRWIlxn2/FAOce/BFPzzdP87H0jwz7SdcuVO1L
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk2 b/regress/unittests/sshkey/testdata/ecdsa_sk2
new file mode 100644
index 000000000..19db5a3f5
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_sk2
@@ -0,0 +1,13 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2
+RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQSTl+SR6rTg
+lOZmcQkCtJ3Pd+lWinezo/gHk4oZdZcTQsmEYs766BlWGuB2Bz3qQRLa6cXsP+4K9kAjAJ
+7zdoFUAAAABHNzaDoAAAGQ1qllJtapZSYAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv
+cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEEk5fkkeq04JTmZnEJArSdz3fpVop3s6P4B5
+OKGXWXE0LJhGLO+ugZVhrgdgc96kES2unF7D/uCvZAIwCe83aBVAAAAARzc2g6AQAAAOMt
+LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJSkxwVkxnSTVvdkRlOW
+VMWmZodCs5WWlMaitnam0rTXhHTXg5NndiRWw0Wm9Bb0dDQ3FHU000OQpBd0VIb1VRRFFn
+QUVrNWZra2VxMDRKVG1abkVKQXJTZHozZnBWb3AzczZQNEI1T0tHWFdYRTBMSmhHTE8rdW
+daClZocmdkZ2M5NmtFUzJ1bkY3RC91Q3ZaQUl3Q2U4M2FCVkE9PQotLS0tLUVORCBFQyBQ
+UklWQVRFIEtFWS0tLS0tCgAAAAAAAAAURUNEU0EtU0sgdGVzdCBrZXkgIzIBAgMEBQ==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk2.fp b/regress/unittests/sshkey/testdata/ecdsa_sk2.fp
new file mode 100644
index 000000000..1bc99ea0d
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_sk2.fp
@@ -0,0 +1 @@
+SHA256:pz8VkgtRY3r50F4zSuzRlmq9c6vPTpJXLKKOgkyUcKE
diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk2.fp.bb b/regress/unittests/sshkey/testdata/ecdsa_sk2.fp.bb
new file mode 100644
index 000000000..bfee7658a
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_sk2.fp.bb
@@ -0,0 +1 @@
+xobel-gavur-gorym-pedop-rarob-bunek-gucer-lofeg-syhaf-fylur-zoxix
diff --git a/regress/unittests/sshkey/testdata/ecdsa_sk2.pub b/regress/unittests/sshkey/testdata/ecdsa_sk2.pub
new file mode 100644
index 000000000..2629d9509
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_sk2.pub
@@ -0,0 +1 @@
+sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBJOX5JHqtOCU5mZxCQK0nc936VaKd7Oj+AeTihl1lxNCyYRizvroGVYa4HYHPepBEtrpxew/7gr2QCMAnvN2gVQAAAAEc3NoOg== ECDSA-SK test key #2
diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1 b/regress/unittests/sshkey/testdata/ed25519_sk1
new file mode 100644
index 000000000..4196d9c6a
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_sk1
@@ -0,0 +1,8 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2
+gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACAhaP5OS1PPOt7uumAvXlDtte9EHbqIT1EZEJ2y
+2v3XMwAAAARzc2g6AAAAuBocY6UaHGOlAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2
+9tAAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDoBAAAAQJYq
+lGHhFoA25/q8X/rdTqDAb7dhqs4ehhd/w8x99CwiIWj+TktTzzre7rpgL15Q7bXvRB26iE
+9RGRCdstr91zMAAAAAAAAAFkVEMjU1MTktU0sgdGVzdCBrZXkgIzEBAgM=
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1-cert.fp b/regress/unittests/sshkey/testdata/ed25519_sk1-cert.fp
new file mode 100644
index 000000000..a6bb1a99c
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_sk1-cert.fp
@@ -0,0 +1 @@
+SHA256:6WZVJ44bqhAWLVP4Ns0TDkoSQSsZo/h2K+mEvOaNFbw
diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1-cert.pub b/regress/unittests/sshkey/testdata/ed25519_sk1-cert.pub
new file mode 100644
index 000000000..3c72c268d
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_sk1-cert.pub
@@ -0,0 +1 @@
+sk-ssh-ed25519-cert-v01@openssh.com AAAAI3NrLXNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIJr7CuMntQKvHoUshx374fJLFEkyxKsEOBA1H6hk5scoAAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDoAAAAAAAAACAAAAAIAAAAGanVsaXVzAAAAEgAAAAVob3N0MQAAAAVob3N0MgAAAAA2i4NgAAAAAE0d4eAAAAAAAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIOo/0xneV3iM2qWEo5RUwvUYa2bjff292T5vvuXRomGQAAAAUwAAAAtzc2gtZWQyNTUxOQAAAECgsRGLDh1SI3m66MRp9D2iLP4wabQ0OrDgGidk7LsVn2XZHV5jBZN1RtNfe6PBMeVzfRtGUzOg18sO7H7uU+EC ED25519-SK test key #1
diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1.fp b/regress/unittests/sshkey/testdata/ed25519_sk1.fp
new file mode 100644
index 000000000..a6bb1a99c
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_sk1.fp
@@ -0,0 +1 @@
+SHA256:6WZVJ44bqhAWLVP4Ns0TDkoSQSsZo/h2K+mEvOaNFbw
diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1.fp.bb b/regress/unittests/sshkey/testdata/ed25519_sk1.fp.bb
new file mode 100644
index 000000000..1bfe20a48
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_sk1.fp.bb
@@ -0,0 +1 @@
+xucac-vusip-tydoz-dudad-nerif-raran-tezun-cogyd-pamoh-bahef-ruxix
diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1.pub b/regress/unittests/sshkey/testdata/ed25519_sk1.pub
new file mode 100644
index 000000000..60fe00c39
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_sk1.pub
@@ -0,0 +1 @@
+sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDo= ED25519-SK test key #1
diff --git a/regress/unittests/sshkey/testdata/ed25519_sk1_pw b/regress/unittests/sshkey/testdata/ed25519_sk1_pw
new file mode 100644
index 000000000..1c29ff07f
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_sk1_pw
@@ -0,0 +1,9 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDr5R9Yf/
+ucEh0Ns6c34tcIAAAAEAAAAAEAAABKAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29t
+AAAAICFo/k5LU8863u66YC9eUO2170QduohPURkQnbLa/dczAAAABHNzaDoAAADA2T6owx
+OSgKz4DvLnS3UJ/renbuew5mbkIWB1/y8xd3y5Usm08iUCAlKxep9dVRQvmyoTrc/7rHOM
+DkokNw+WgKambnlYT/9QfqViZ9iCBtbdmhLM6ksUCgQefvquRyXoJxlWstjXUll6Ru+ZbT
+H//Ss8C1bYtAiXR68OQ+rhDrvQxA9P8J1sGIlkuV3h8YXddSpyBW2Sn0LTHHBXYZo86cXZ
+G4Lnc8aGYm65eqdHgkfRmht3eS8DTdzEBfBNH5Ml
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ed25519_sk2 b/regress/unittests/sshkey/testdata/ed25519_sk2
new file mode 100644
index 000000000..b9b748966
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_sk2
@@ -0,0 +1,8 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2
+gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACAV8fu1Sc31QLK2R/zGPdN3ve5xuFvDc7mEAWxb
+aI+YcwAAAARzc2g6AAAAuJCMX5uQjF+bAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2
+9tAAAAIBXx+7VJzfVAsrZH/MY903e97nG4W8NzuYQBbFtoj5hzAAAABHNzaDoBAAAAQObE
+PajcKI1W30EKOhBb6u+Fgx464kf7EjnqDSg4l7gAFfH7tUnN9UCytkf8xj3Td73ucbhbw3
+O5hAFsW2iPmHMAAAAAAAAAFkVEMjU1MTktU0sgdGVzdCBrZXkgIzIBAgM=
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ed25519_sk2.fp b/regress/unittests/sshkey/testdata/ed25519_sk2.fp
new file mode 100644
index 000000000..1c4369a00
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_sk2.fp
@@ -0,0 +1 @@
+SHA256:b9BVPS5vuU4yu/FgweojLLg6zbfmBBoWLUgibdxxsoo
diff --git a/regress/unittests/sshkey/testdata/ed25519_sk2.fp.bb b/regress/unittests/sshkey/testdata/ed25519_sk2.fp.bb
new file mode 100644
index 000000000..f5fd9efd8
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_sk2.fp.bb
@@ -0,0 +1 @@
+xemac-tizim-dihep-supar-zupib-cukak-pasis-febeg-dyguv-hutec-dyxox
diff --git a/regress/unittests/sshkey/testdata/ed25519_sk2.pub b/regress/unittests/sshkey/testdata/ed25519_sk2.pub
new file mode 100644
index 000000000..c7ed9f524
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_sk2.pub
@@ -0,0 +1 @@
+sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIBXx+7VJzfVAsrZH/MY903e97nG4W8NzuYQBbFtoj5hzAAAABHNzaDo= ED25519-SK test key #2
diff --git a/regress/unittests/sshsig/Makefile b/regress/unittests/sshsig/Makefile
new file mode 100644
index 000000000..65564d1b2
--- /dev/null
+++ b/regress/unittests/sshsig/Makefile
@@ -0,0 +1,25 @@
+# $OpenBSD: Makefile,v 1.2 2021/01/09 12:24:31 dtucker Exp $
+
+PROG=test_sshsig
+SRCS=tests.c
+
+# From usr.bin/ssh
+SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
+SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c
+SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c
+SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c
+SRCS+=addr.c addrmatch.c bitmap.c sshsig.c
+SRCS+=ed25519.c hash.c ge25519.c fe25519.c sc25519.c verify.c
+SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c
+SRCS+=ssh-ed25519-sk.c sk-usbhid.c
+
+SRCS+=digest-openssl.c
+#SRCS+=digest-libc.c
+SRCS+=utf8.c
+
+REGRESS_TARGETS=run-regress-${PROG}
+
+run-regress-${PROG}: ${PROG}
+ env ${TEST_ENV} ./${PROG} ${UNITTEST_ARGS} -d ${.CURDIR}/testdata
+
+.include <bsd.regress.mk>
diff --git a/regress/unittests/sshsig/mktestdata.sh b/regress/unittests/sshsig/mktestdata.sh
new file mode 100755
index 000000000..d2300f9c6
--- /dev/null
+++ b/regress/unittests/sshsig/mktestdata.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+# $OpenBSD: mktestdata.sh,v 1.1 2020/06/19 04:32:09 djm Exp $
+
+NAMESPACE=unittest
+
+set -ex
+
+cd testdata
+
+if [ -f ../../../misc/sk-dummy/sk-dummy.so ] ; then
+ SK_DUMMY=../../../misc/sk-dummy/sk-dummy.so
+elif [ -f ../../../misc/sk-dummy/obj/sk-dummy.so ] ; then
+ SK_DUMMY=../../../misc/sk-dummy/obj/sk-dummy.so
+else
+ echo "Can't find sk-dummy.so" 1>&2
+ exit 1
+fi
+
+rm -f signed-data namespace
+rm -f rsa dsa ecdsa ed25519 ecdsa_sk ed25519_sk
+rm -f rsa.sig dsa.sig ecdsa.sig ed25519.sig ecdsa_sk.sig ed25519_sk.sig
+
+printf "This is a test, this is only a test" > signed-data
+printf "$NAMESPACE" > namespace
+
+ssh-keygen -t rsa -C "RSA test" -N "" -f rsa -m PEM
+ssh-keygen -t dsa -C "DSA test" -N "" -f dsa -m PEM
+ssh-keygen -t ecdsa -C "ECDSA test" -N "" -f ecdsa -m PEM
+ssh-keygen -t ed25519 -C "ED25519 test key" -N "" -f ed25519
+ssh-keygen -w "$SK_DUMMY" -t ecdsa-sk -C "ECDSA-SK test key" \
+ -N "" -f ecdsa_sk
+ssh-keygen -w "$SK_DUMMY" -t ed25519-sk -C "ED25519-SK test key" \
+ -N "" -f ed25519_sk
+
+ssh-keygen -Y sign -f rsa -n $NAMESPACE - < signed-data > rsa.sig
+ssh-keygen -Y sign -f dsa -n $NAMESPACE - < signed-data > dsa.sig
+ssh-keygen -Y sign -f ecdsa -n $NAMESPACE - < signed-data > ecdsa.sig
+ssh-keygen -Y sign -f ed25519 -n $NAMESPACE - < signed-data > ed25519.sig
+ssh-keygen -w "$SK_DUMMY" \
+ -Y sign -f ecdsa_sk -n $NAMESPACE - < signed-data > ecdsa_sk.sig
+ssh-keygen -w "$SK_DUMMY" \
+ -Y sign -f ed25519_sk -n $NAMESPACE - < signed-data > ed25519_sk.sig
diff --git a/regress/unittests/sshsig/testdata/dsa b/regress/unittests/sshsig/testdata/dsa
new file mode 100644
index 000000000..7c0063efc
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/dsa
@@ -0,0 +1,12 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQCXpndQdz2mQVnk+lYOF3nxDT+h6SiJmUvBFhnFWBv8tG4pTOkb
+EwGufLEzGpzjTj+3bjVau7LFt37AFrqs4Num272BWNsYNIjOlGPgq7Xjv32FN00x
+JYh1DoRs1cGGnvohlsWEamGGhTHD1a9ipctPEBV+NrxtZMrl+pO/ZZg8vQIVAKJB
+P3iNYSpSuW74+q4WxLCuK8O3AoGAQldE+BIuxlvoG1IFiWesx0CU+H2KO0SEZc9A
+SX/qjOabh0Fb78ofTlEf9gWHFfat8SvSJQIOPMVlb76Lio8AAMT8Eaa/qQKKYmQL
+dNq4MLhhjxx5KLGt6J2JyFPExCv+qnHYHD59ngtLwKyqGjpSC8LPLktdXn8W/Aad
+Ly1K7+MCgYBsMHBczhSeUh8w7i20CVg4OlNTmfJRVU2tO6OpMxZ/quitRm3hLKSN
+u4xRkvHJwi4LhQtv1SXvLI5gs5P3gCG8tsIAiyCqLinHha63iBdJpqhnV/x/j7dB
+yJr3xJbnmLdWLkkCtNk1Ir1/CuEz+ufAyLGdKWksEAu1UUlb501BkwIVAILIa3Rg
+0h7J9lQpHJphvF3K0M1T
+-----END DSA PRIVATE KEY-----
diff --git a/regress/unittests/sshsig/testdata/dsa.pub b/regress/unittests/sshsig/testdata/dsa.pub
new file mode 100644
index 000000000..e77aa7ef4
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/dsa.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAJemd1B3PaZBWeT6Vg4XefENP6HpKImZS8EWGcVYG/y0bilM6RsTAa58sTManONOP7duNVq7ssW3fsAWuqzg26bbvYFY2xg0iM6UY+CrteO/fYU3TTEliHUOhGzVwYae+iGWxYRqYYaFMcPVr2Kly08QFX42vG1kyuX6k79lmDy9AAAAFQCiQT94jWEqUrlu+PquFsSwrivDtwAAAIBCV0T4Ei7GW+gbUgWJZ6zHQJT4fYo7RIRlz0BJf+qM5puHQVvvyh9OUR/2BYcV9q3xK9IlAg48xWVvvouKjwAAxPwRpr+pAopiZAt02rgwuGGPHHkosa3onYnIU8TEK/6qcdgcPn2eC0vArKoaOlILws8uS11efxb8Bp0vLUrv4wAAAIBsMHBczhSeUh8w7i20CVg4OlNTmfJRVU2tO6OpMxZ/quitRm3hLKSNu4xRkvHJwi4LhQtv1SXvLI5gs5P3gCG8tsIAiyCqLinHha63iBdJpqhnV/x/j7dByJr3xJbnmLdWLkkCtNk1Ir1/CuEz+ufAyLGdKWksEAu1UUlb501Bkw== DSA test
diff --git a/regress/unittests/sshsig/testdata/dsa.sig b/regress/unittests/sshsig/testdata/dsa.sig
new file mode 100644
index 000000000..0b14ad6b8
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/dsa.sig
@@ -0,0 +1,13 @@
+-----BEGIN SSH SIGNATURE-----
+U1NIU0lHAAAAAQAAAbEAAAAHc3NoLWRzcwAAAIEAl6Z3UHc9pkFZ5PpWDhd58Q0/oekoiZ
+lLwRYZxVgb/LRuKUzpGxMBrnyxMxqc404/t241Wruyxbd+wBa6rODbptu9gVjbGDSIzpRj
+4Ku14799hTdNMSWIdQ6EbNXBhp76IZbFhGphhoUxw9WvYqXLTxAVfja8bWTK5fqTv2WYPL
+0AAAAVAKJBP3iNYSpSuW74+q4WxLCuK8O3AAAAgEJXRPgSLsZb6BtSBYlnrMdAlPh9ijtE
+hGXPQEl/6ozmm4dBW+/KH05RH/YFhxX2rfEr0iUCDjzFZW++i4qPAADE/BGmv6kCimJkC3
+TauDC4YY8ceSixreidichTxMQr/qpx2Bw+fZ4LS8Csqho6UgvCzy5LXV5/FvwGnS8tSu/j
+AAAAgGwwcFzOFJ5SHzDuLbQJWDg6U1OZ8lFVTa07o6kzFn+q6K1GbeEspI27jFGS8cnCLg
+uFC2/VJe8sjmCzk/eAIby2wgCLIKouKceFrreIF0mmqGdX/H+Pt0HImvfElueYt1YuSQK0
+2TUivX8K4TP658DIsZ0paSwQC7VRSVvnTUGTAAAACHVuaXR0ZXN0AAAAAAAAAAZzaGE1MT
+IAAAA3AAAAB3NzaC1kc3MAAAAodi5lr0pqBpO76OY4N1CtfR85BCgZ95qfVjP/e9lToj0q
+lwjSJJXUjw==
+-----END SSH SIGNATURE-----
diff --git a/regress/unittests/sshsig/testdata/ecdsa b/regress/unittests/sshsig/testdata/ecdsa
new file mode 100644
index 000000000..55fb440e0
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/ecdsa
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIFg0ZCSEB5LNeLsXYL25g3kqEWsqh52DR+yNOjyQJqyZoAoGCCqGSM49
+AwEHoUQDQgAE3sud88FV0N8FPspZSV7LWqj6uPPLRZiSsenNuEYAteWPyDgrZsWb
+LzXBuUJucepaCNuW/QWgHBRbrjWj3ERm3A==
+-----END EC PRIVATE KEY-----
diff --git a/regress/unittests/sshsig/testdata/ecdsa.pub b/regress/unittests/sshsig/testdata/ecdsa.pub
new file mode 100644
index 000000000..14ec6cf12
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/ecdsa.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBN7LnfPBVdDfBT7KWUley1qo+rjzy0WYkrHpzbhGALXlj8g4K2bFmy81wblCbnHqWgjblv0FoBwUW641o9xEZtw= ECDSA test
diff --git a/regress/unittests/sshsig/testdata/ecdsa.sig b/regress/unittests/sshsig/testdata/ecdsa.sig
new file mode 100644
index 000000000..79781570c
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/ecdsa.sig
@@ -0,0 +1,7 @@
+-----BEGIN SSH SIGNATURE-----
+U1NIU0lHAAAAAQAAAGgAAAATZWNkc2Etc2hhMi1uaXN0cDI1NgAAAAhuaXN0cDI1NgAAAE
+EE3sud88FV0N8FPspZSV7LWqj6uPPLRZiSsenNuEYAteWPyDgrZsWbLzXBuUJucepaCNuW
+/QWgHBRbrjWj3ERm3AAAAAh1bml0dGVzdAAAAAAAAAAGc2hhNTEyAAAAZQAAABNlY2RzYS
+1zaGEyLW5pc3RwMjU2AAAASgAAACEAycVNsTlE+XEZYyYiDxWZlliruf/pPMhEEMR/XLdQ
+a4MAAAAhALQt+5gES7L3uKGptHB6UZQMuZ2WyI0C6FJs4v6AtMIU
+-----END SSH SIGNATURE-----
diff --git a/regress/unittests/sshsig/testdata/ecdsa_sk b/regress/unittests/sshsig/testdata/ecdsa_sk
new file mode 100644
index 000000000..62ae44cb0
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/ecdsa_sk
@@ -0,0 +1,13 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAfwAAACJzay1lY2
+RzYS1zaGEyLW5pc3RwMjU2QG9wZW5zc2guY29tAAAACG5pc3RwMjU2AAAAQQSg1WuY0XE+
+VexOsrJsFYuxyVoe6eQ/oXmyz2pEHKZw9moyWehv+Fs7oZWFp3JVmOtybKQ6dvfUZYauQE
+/Ov4PAAAAABHNzaDoAAAGI6iV41+oleNcAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBv
+cGVuc3NoLmNvbQAAAAhuaXN0cDI1NgAAAEEEoNVrmNFxPlXsTrKybBWLsclaHunkP6F5ss
+9qRBymcPZqMlnob/hbO6GVhadyVZjrcmykOnb31GWGrkBPzr+DwAAAAARzc2g6AQAAAOMt
+LS0tLUJFR0lOIEVDIFBSSVZBVEUgS0VZLS0tLS0KTUhjQ0FRRUVJQm9oeW54M2tpTFVEeS
+t5UjU3WXBXSU5KektnU1p6WnV2VTljYXFla3JGcW9Bb0dDQ3FHU000OQpBd0VIb1VRRFFn
+QUVvTlZybU5GeFBsWHNUckt5YkJXTHNjbGFIdW5rUDZGNXNzOXFSQnltY1BacU1sbm9iL2
+hiCk82R1ZoYWR5VlpqcmNteWtPbmIzMUdXR3JrQlB6citEd0E9PQotLS0tLUVORCBFQyBQ
+UklWQVRFIEtFWS0tLS0tCgAAAAAAAAARRUNEU0EtU0sgdGVzdCBrZXk=
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshsig/testdata/ecdsa_sk.pub b/regress/unittests/sshsig/testdata/ecdsa_sk.pub
new file mode 100644
index 000000000..385ebf15b
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/ecdsa_sk.pub
@@ -0,0 +1 @@
+sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBKDVa5jRcT5V7E6ysmwVi7HJWh7p5D+hebLPakQcpnD2ajJZ6G/4WzuhlYWnclWY63JspDp299Rlhq5AT86/g8AAAAAEc3NoOg== ECDSA-SK test key
diff --git a/regress/unittests/sshsig/testdata/ecdsa_sk.sig b/regress/unittests/sshsig/testdata/ecdsa_sk.sig
new file mode 100644
index 000000000..86de36063
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/ecdsa_sk.sig
@@ -0,0 +1,8 @@
+-----BEGIN SSH SIGNATURE-----
+U1NIU0lHAAAAAQAAAH8AAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBvcGVuc3NoLmNvbQ
+AAAAhuaXN0cDI1NgAAAEEEoNVrmNFxPlXsTrKybBWLsclaHunkP6F5ss9qRBymcPZqMlno
+b/hbO6GVhadyVZjrcmykOnb31GWGrkBPzr+DwAAAAARzc2g6AAAACHVuaXR0ZXN0AAAAAA
+AAAAZzaGE1MTIAAAB3AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20A
+AABIAAAAIHohGwyy8iKT3zwd1TYA9V/Ioo7h/3zCJUtyq/Qigt/HAAAAIGzidTwq7D/kFa
+7Xjcp/KkdbIs4MfQpfAW/0OciajlpzARI0Vng=
+-----END SSH SIGNATURE-----
diff --git a/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.pub b/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.pub
new file mode 100644
index 000000000..1597302ce
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.pub
@@ -0,0 +1 @@
+sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBBRGwDjs4HhJFcn4tJ5Gr72KcmRmCS1OirETxaXvnsNApgoOLF1a/7rxldfSMHm73eT1nhHe97W8qicPPEAKDJQAAAALbWluZHJvdC5vcmc=
diff --git a/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.sig b/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.sig
new file mode 100644
index 000000000..4bdd8edc6
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/ecdsa_sk_webauthn.sig
@@ -0,0 +1,13 @@
+-----BEGIN SSH SIGNATURE-----
+U1NIU0lHAAAAAQAAAIYAAAAic2stZWNkc2Etc2hhMi1uaXN0cDI1NkBvcGVuc3NoLmNvbQ
+AAAAhuaXN0cDI1NgAAAEEEFEbAOOzgeEkVyfi0nkavvYpyZGYJLU6KsRPFpe+ew0CmCg4s
+XVr/uvGV19Iwebvd5PWeEd73tbyqJw88QAoMlAAAAAttaW5kcm90Lm9yZwAAAAh1bml0dG
+VzdAAAAAAAAAAGc2hhNTEyAAABhwAAACt3ZWJhdXRobi1zay1lY2RzYS1zaGEyLW5pc3Rw
+MjU2QG9wZW5zc2guY29tAAAASQAAACBj2oMT9tb5wRXe6mdmf4/lgAO8wrgr95ouozwNg4
+itnQAAACEAtU9g5wz3HchUiLfLD6plr9T4TiJ32lVCrATSjpiy0SMBAAADHwAAABdodHRw
+czovL3d3dy5taW5kcm90Lm9yZwAAAON7InR5cGUiOiJ3ZWJhdXRobi5nZXQiLCJjaGFsbG
+VuZ2UiOiJVMU5JVTBsSEFBQUFDSFZ1YVhSMFpYTjBBQUFBQUFBQUFBWnphR0UxTVRJQUFB
+QkFMTHU4WmdjU3h0Nk1zRlV6dWlaZ0c2R3dNZEo5ZDd4ZUU3WW9SSXcwZzlpSEpfd3NGRD
+cxbzRXbHllenZGV0VqYnFRMHFDN0Z3R3Bqa2pVUVAtTmQ2dyIsIm9yaWdpbiI6Imh0dHBz
+Oi8vd3d3Lm1pbmRyb3Qub3JnIiwiY3Jvc3NPcmlnaW4iOmZhbHNlfQAAAAA=
+-----END SSH SIGNATURE-----
diff --git a/regress/unittests/sshsig/testdata/ed25519 b/regress/unittests/sshsig/testdata/ed25519
new file mode 100644
index 000000000..b44a63d3e
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/ed25519
@@ -0,0 +1,7 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
+QyNTUxOQAAACCJYs0iDdw0Fe/FTzY1b78I4H/j+R6mz2AmLtwTjHYwBAAAAJjpGas/6Rmr
+PwAAAAtzc2gtZWQyNTUxOQAAACCJYs0iDdw0Fe/FTzY1b78I4H/j+R6mz2AmLtwTjHYwBA
+AAAEDpSKRA1QKW6kYiQftGRWh+H0fNekzYLG6c3bzseoCpEolizSIN3DQV78VPNjVvvwjg
+f+P5HqbPYCYu3BOMdjAEAAAAEEVEMjU1MTkgdGVzdCBrZXkBAgMEBQ==
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshsig/testdata/ed25519.pub b/regress/unittests/sshsig/testdata/ed25519.pub
new file mode 100644
index 000000000..b078e4516
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/ed25519.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIlizSIN3DQV78VPNjVvvwjgf+P5HqbPYCYu3BOMdjAE ED25519 test key
diff --git a/regress/unittests/sshsig/testdata/ed25519.sig b/regress/unittests/sshsig/testdata/ed25519.sig
new file mode 100644
index 000000000..8e8ff2a8a
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/ed25519.sig
@@ -0,0 +1,6 @@
+-----BEGIN SSH SIGNATURE-----
+U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgiWLNIg3cNBXvxU82NW+/COB/4/
+keps9gJi7cE4x2MAQAAAAIdW5pdHRlc3QAAAAAAAAABnNoYTUxMgAAAFMAAAALc3NoLWVk
+MjU1MTkAAABAihQsbUzuNEFflk5Tw1+H9aLS7tZQk0RG8KW1DtOmDYYnWe3D3UKiG3fcJa
+DNg4vBWp1j1gLRiBMOF+gwYNegDg==
+-----END SSH SIGNATURE-----
diff --git a/regress/unittests/sshsig/testdata/ed25519_sk b/regress/unittests/sshsig/testdata/ed25519_sk
new file mode 100644
index 000000000..3a434ecb9
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/ed25519_sk
@@ -0,0 +1,8 @@
+-----BEGIN OPENSSH PRIVATE KEY-----
+b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2
+gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACCbGg2F0GK7nOm4pQmAyCuGEjnhvs5q0TtjPbdN
+//+yxwAAAARzc2g6AAAAuBw56jAcOeowAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2
+9tAAAAIJsaDYXQYruc6bilCYDIK4YSOeG+zmrRO2M9t03//7LHAAAABHNzaDoBAAAAQFXc
+6dCwWewIk1EBofAouGZApW8+s0XekXenxtb78+x0mxoNhdBiu5zpuKUJgMgrhhI54b7Oat
+E7Yz23Tf//sscAAAAAAAAAE0VEMjU1MTktU0sgdGVzdCBrZXkBAgMEBQY=
+-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshsig/testdata/ed25519_sk.pub b/regress/unittests/sshsig/testdata/ed25519_sk.pub
new file mode 100644
index 000000000..71051ec3b
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/ed25519_sk.pub
@@ -0,0 +1 @@
+sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJsaDYXQYruc6bilCYDIK4YSOeG+zmrRO2M9t03//7LHAAAABHNzaDo= ED25519-SK test key
diff --git a/regress/unittests/sshsig/testdata/ed25519_sk.sig b/regress/unittests/sshsig/testdata/ed25519_sk.sig
new file mode 100644
index 000000000..49b6818da
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/ed25519_sk.sig
@@ -0,0 +1,7 @@
+-----BEGIN SSH SIGNATURE-----
+U1NIU0lHAAAAAQAAAEoAAAAac2stc3NoLWVkMjU1MTlAb3BlbnNzaC5jb20AAAAgmxoNhd
+Biu5zpuKUJgMgrhhI54b7OatE7Yz23Tf//sscAAAAEc3NoOgAAAAh1bml0dGVzdAAAAAAA
+AAAGc2hhNTEyAAAAZwAAABpzay1zc2gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAAEAi+7eTjW
+/+LQ2M+sCD+KFtH1n7VFFJon/SZFsxODyV8cWTlFKj617Ys1Ur5TV6uaEXQhck8rBA2oQI
+HTPANLIPARI0Vng=
+-----END SSH SIGNATURE-----
diff --git a/regress/unittests/sshsig/testdata/namespace b/regress/unittests/sshsig/testdata/namespace
new file mode 100644
index 000000000..1570cd548
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/namespace
@@ -0,0 +1 @@
+unittest \ No newline at end of file
diff --git a/regress/unittests/sshsig/testdata/rsa b/regress/unittests/sshsig/testdata/rsa
new file mode 100644
index 000000000..228fad797
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/rsa
@@ -0,0 +1,39 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIG4wIBAAKCAYEA386lmjRHtJpyj87BrS+ssMmtvc/1SPN0gXTPs9jZ1hYAq98P
+ca3/RYVM4HaSu6COztQJ2ZnZD3Te/XeBnIU2mfuvQEl+DiwisGeNglVyRCi7787f
+PFFfcxzZfDa7EB2qY8S3oaSGZK8QqzuGwmGAImjlQXz6J+HCd/eD/58GoCSSirIE
+CFWCAt+uNrOC/EmgAzsbfcfaIbbVzA40tlgU3hO2J42kddz8CisDTtDKQABFcOaQ
+ZycSfn7HDP+WgXLXXBUI9wVM1Tif1f+9MX08xIsvCvGzo7yLgbbTFLSGr5SkA+tO
+rYuoA7V8fge0id/3pnVtG1Ui3I7vejeAwf0HZqtFeBEnOwkIJFmZeMtFeOVf+4ki
+4h1rDqAvSscNvMtLp6OXpbAATATAuEWEkIQBl1rngnEe0iC9iU9itKMW6qJ4FtIb
+4ACH1EoU1x8vqrFecg2hvqfk5CZBJIbV28JFuGjac3OxBZ17Fqb8ljomUir1GrET
+2z66NMgb5TjDD7BVAgMBAAECggGACfjDGCPMLhfTkuS7bGP7ZcUWoKZrX1y5jCsQ
+NgsraYaBcSb3ITGHdimCS139G68DreN0rOVV7oJejRyOAdNNo367SDn+C9ObmBCF
+FZGJDdBiz0SAXceiYRaf+hDWNNmdheR16hXShxnlvDtivbZqZx4VWN2gp7Y/W+kD
+UJhdSzVV8igMVfK5YDdnI7jL1UHSh1JS3z/QUEA9NmJLpvQ1uc9XBlwhP78g27Me
+6pwS5tccQPOE65OqF0i+xa19nzbmnC940Y34yZeI/UE+PYaO2+asapvOfu/sboBH
+Yb5BuWXVEkSeRWI23SpuZbmfNTtVgiRoRqOvqM4G88LkhYjZ6xpDggxQwJiShiiD
+oWCucs0v3pX8H8/LbGs8l50SGI5nzUqAdZ7/QQucU/GuDiQtampntkLEDgf9KIw/
+SDrtCw1E9fnCWj4Z71IYfepY9bVY6QUEcfTdnDcYSY1Z5tVpzeMHVLeo0lbNVZv9
+2qmPnjjP/IvWbjjwu/PHpUWkUs0BAoHBAPx4YwPXWYgWnesMKXkjAHyO5KA4EyBr
++rcEmOZkZDibC8PKYzIK2ztptuthahVovW20R/QJhJkO5teGZMeGPFq+floCeC5P
+la9CEYGYcTrzgSe1QM9IGMr1vGI1KIWck7VkJ0bkKoY40uIJSVZxnyG9pEpcwYSp
+tnOqA/f5YZUFctWvXUz46OfiLKstXLrcrGIU7YRmLv2rW9twnpJYTzE98g3KpVJ2
+TI1pyvrDTdGeAQUTGCAjpviY6XR5d020vQKBwQDi76wsGLQ3XLI+OAE95Ljo0Mcl
++KdJPVVQPq/VcjKgZQndFloflMRrmgNHme9gmsHOrf8DLZvEDbtT+gbmWslMFZQ9
+om1kR404gfuGmfIYdBdOwWjuBLsZs3pfqDB4Xa3NkxljwOMYTp035n0r2UMFaSy3
+gvpW7fsdPOGAJsqNhSw/JNHcokHeBm7VbV0aD7tSyIghmARb5c98fmrSPbiEo8mP
+ITIZlgbfZCq2KuXY4q16R3QvlpuSwitVobLR/3kCgcEAueH5JM7dQHFGe9RMhL/c
+j9i1Q7GFg4183lsoKBkqIPMmylSsjB+qIihHYS4r6O9g6PCfOXH4iqiKFY0BjlWr
+AjTW2naO/aniz1KZiQ0v8PNv2Eh/Gx4+AtDCjpwM5bLOnfLLaEp9dK1JttqXgGnP
+fAwgdg+s+3votWgr29tkmU+VqPagfxeUg4Xm1XFkoL/wu5Yk+iIx3trXms1kMuOK
+CvtMyBK3fetTmZqWs+Iv3XGz1oSkcqVNPiN3XyY/TJsRAoG/Q17jvjOXTNg4EkCO
+HdHJE1Tnyl4HS7bpnOj/Sl6cqQFV7Ey2dKm1pjwSvS714bgP0UvWaRshIxLwif2w
+DrLlD7FYUPPnhd24Dw6HnW4WcSwFv1uryv2cjgS6T6ueuB0Xe/AvmW2p/Y1ZHz9N
+6baWLwUKQXCg4S3FXui0CVd6yoi+mgBUTSveYguG29WbziDde7YMs+xtXtravhrJ
+m6C3Jql5LQSt2uqvH6KdC3ewxLKGzcZot7f+d5MtSj6216ECgcEA9PGmWeUkhVuW
+Xz2c9iBeHwCtmDso7gVwxNnHqdqirB4f1nDCGbrJS7hz5Ss7/wfzekP2W5if2P6U
+JPUdfykAQgALNn1twAtj1a+UAp31ZWu8JK/Qzt4hLJPBxzMo7MenJq189JmYmDnm
+6D5d9vDLCW15gCZua89GZa8K8V50lYyeHBOHAyzNTfNlnMBkHyP645+nqpuEWzIT
+3mCe2OAbl60o8VvvVUlAQyQ/ObLq37HHEoDu0U/YAnP157cxpa84
+-----END RSA PRIVATE KEY-----
diff --git a/regress/unittests/sshsig/testdata/rsa.pub b/regress/unittests/sshsig/testdata/rsa.pub
new file mode 100644
index 000000000..30142ac0a
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/rsa.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDfzqWaNEe0mnKPzsGtL6ywya29z/VI83SBdM+z2NnWFgCr3w9xrf9FhUzgdpK7oI7O1AnZmdkPdN79d4GchTaZ+69ASX4OLCKwZ42CVXJEKLvvzt88UV9zHNl8NrsQHapjxLehpIZkrxCrO4bCYYAiaOVBfPon4cJ394P/nwagJJKKsgQIVYIC3642s4L8SaADOxt9x9ohttXMDjS2WBTeE7YnjaR13PwKKwNO0MpAAEVw5pBnJxJ+fscM/5aBctdcFQj3BUzVOJ/V/70xfTzEiy8K8bOjvIuBttMUtIavlKQD606ti6gDtXx+B7SJ3/emdW0bVSLcju96N4DB/Qdmq0V4ESc7CQgkWZl4y0V45V/7iSLiHWsOoC9Kxw28y0uno5elsABMBMC4RYSQhAGXWueCcR7SIL2JT2K0oxbqongW0hvgAIfUShTXHy+qsV5yDaG+p+TkJkEkhtXbwkW4aNpzc7EFnXsWpvyWOiZSKvUasRPbPro0yBvlOMMPsFU= RSA test
diff --git a/regress/unittests/sshsig/testdata/rsa.sig b/regress/unittests/sshsig/testdata/rsa.sig
new file mode 100644
index 000000000..15a032e01
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/rsa.sig
@@ -0,0 +1,19 @@
+-----BEGIN SSH SIGNATURE-----
+U1NIU0lHAAAAAQAAAZcAAAAHc3NoLXJzYQAAAAMBAAEAAAGBAN/OpZo0R7Saco/Owa0vrL
+DJrb3P9UjzdIF0z7PY2dYWAKvfD3Gt/0WFTOB2krugjs7UCdmZ2Q903v13gZyFNpn7r0BJ
+fg4sIrBnjYJVckQou+/O3zxRX3Mc2Xw2uxAdqmPEt6GkhmSvEKs7hsJhgCJo5UF8+ifhwn
+f3g/+fBqAkkoqyBAhVggLfrjazgvxJoAM7G33H2iG21cwONLZYFN4TtieNpHXc/AorA07Q
+ykAARXDmkGcnEn5+xwz/loFy11wVCPcFTNU4n9X/vTF9PMSLLwrxs6O8i4G20xS0hq+UpA
+PrTq2LqAO1fH4HtInf96Z1bRtVItyO73o3gMH9B2arRXgRJzsJCCRZmXjLRXjlX/uJIuId
+aw6gL0rHDbzLS6ejl6WwAEwEwLhFhJCEAZda54JxHtIgvYlPYrSjFuqieBbSG+AAh9RKFN
+cfL6qxXnINob6n5OQmQSSG1dvCRbho2nNzsQWdexam/JY6JlIq9RqxE9s+ujTIG+U4ww+w
+VQAAAAh1bml0dGVzdAAAAAAAAAAGc2hhNTEyAAABlAAAAAxyc2Etc2hhMi01MTIAAAGACi
+nEpBrQxZi0yOrrT6h98JFfZh0XXioih4fzmvtoV0yOReWClS+otGgXoJyZHcbaKNOjDwSM
+rIkUoX6OUJmtHYP0HRELnKw35m33LdBPXpFGS4tRS7NeSpvc04KtjT6jYXY9FjWy5hcn17
+Sxc/3DnJqLgJBur8acY7FeIzpWmKixPd/dGkEjdWoD9gO6szLczGuQgrOdYmSRL4yKadTJ
+lVjz5OSeKSYYGQy33US2XQassRRNYf4e9byTA3DKvHa/OcTt7lFerea0kZdDpAboqffz7T
+Yaw/hFskAYLIEdTW3aoXBGHSOvu8AkDOtb7qwuxGSQ27pjkDLDNsp1ceCFaCaQ6X83RZuK
+ACv9JUBI5KaSf81e0bs0KezJKkhB9czeZ6dk96qISbgayEBnvhYgXvUDKtHn7HzNlCJKfK
+5ABhNxfGG2CD+NKqcrndwFgS1sQO3hbA84zPQb26ShBovT8ytHBmW1F8ZK4O9Bz61Q6EZK
+vs/u6xP6LUean/so5daa
+-----END SSH SIGNATURE-----
diff --git a/regress/unittests/sshsig/testdata/signed-data b/regress/unittests/sshsig/testdata/signed-data
new file mode 100644
index 000000000..7df4bedd1
--- /dev/null
+++ b/regress/unittests/sshsig/testdata/signed-data
@@ -0,0 +1 @@
+This is a test, this is only a test \ No newline at end of file
diff --git a/regress/unittests/sshsig/tests.c b/regress/unittests/sshsig/tests.c
new file mode 100644
index 000000000..bf59d58d1
--- /dev/null
+++ b/regress/unittests/sshsig/tests.c
@@ -0,0 +1,139 @@
+/* $OpenBSD: tests.c,v 1.2 2020/06/22 06:00:06 djm Exp $ */
+/*
+ * Regress test for sshbuf.h buffer API
+ *
+ * Placed in the public domain
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/evp.h>
+#include <openssl/crypto.h>
+
+#include "ssherr.h"
+#include "authfile.h"
+#include "sshkey.h"
+#include "sshbuf.h"
+#include "sshsig.h"
+#include "log.h"
+
+#include "../test_helper/test_helper.h"
+
+static struct sshbuf *
+load_file(const char *name)
+{
+ struct sshbuf *ret = NULL;
+
+ ASSERT_INT_EQ(sshbuf_load_file(test_data_file(name), &ret), 0);
+ ASSERT_PTR_NE(ret, NULL);
+ return ret;
+}
+
+static struct sshkey *
+load_key(const char *name)
+{
+ struct sshkey *ret = NULL;
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file(name), &ret, NULL), 0);
+ ASSERT_PTR_NE(ret, NULL);
+ return ret;
+}
+
+static void
+check_sig(const char *keyname, const char *signame, const struct sshbuf *msg,
+ const char *namespace)
+{
+ struct sshkey *k, *sign_key;
+ struct sshbuf *sig, *rawsig;
+ struct sshkey_sig_details *sig_details;
+
+ k = load_key(keyname);
+ sig = load_file(signame);
+ sign_key = NULL;
+ sig_details = NULL;
+ rawsig = NULL;
+ ASSERT_INT_EQ(sshsig_dearmor(sig, &rawsig), 0);
+ ASSERT_INT_EQ(sshsig_verifyb(rawsig, msg, namespace,
+ &sign_key, &sig_details), 0);
+ ASSERT_INT_EQ(sshkey_equal(k, sign_key), 1);
+ sshkey_free(k);
+ sshkey_free(sign_key);
+ sshkey_sig_details_free(sig_details);
+ sshbuf_free(sig);
+ sshbuf_free(rawsig);
+}
+
+void
+tests(void)
+{
+ struct sshbuf *msg;
+ char *namespace;
+
+#if 0
+ log_init("test_sshsig", SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 1);
+#endif
+
+#ifdef WITH_OPENSSL
+ OpenSSL_add_all_algorithms();
+ ERR_load_CRYPTO_strings();
+#endif
+
+ TEST_START("load data");
+ msg = load_file("namespace");
+ namespace = sshbuf_dup_string(msg);
+ ASSERT_PTR_NE(namespace, NULL);
+ sshbuf_free(msg);
+ msg = load_file("signed-data");
+ TEST_DONE();
+
+#ifdef WITH_OPENSSL
+ TEST_START("check RSA signature");
+ check_sig("rsa.pub", "rsa.sig", msg, namespace);
+ TEST_DONE();
+
+ TEST_START("check DSA signature");
+ check_sig("dsa.pub", "dsa.sig", msg, namespace);
+ TEST_DONE();
+
+#ifdef OPENSSL_HAS_ECC
+ TEST_START("check ECDSA signature");
+ check_sig("ecdsa.pub", "ecdsa.sig", msg, namespace);
+ TEST_DONE();
+#endif
+#endif
+
+ TEST_START("check ED25519 signature");
+ check_sig("ed25519.pub", "ed25519.sig", msg, namespace);
+ TEST_DONE();
+
+#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
+ TEST_START("check ECDSA-SK signature");
+ check_sig("ecdsa_sk.pub", "ecdsa_sk.sig", msg, namespace);
+ TEST_DONE();
+#endif
+
+ TEST_START("check ED25519-SK signature");
+ check_sig("ed25519_sk.pub", "ed25519_sk.sig", msg, namespace);
+ TEST_DONE();
+
+#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
+ TEST_START("check ECDSA-SK webauthn signature");
+ check_sig("ecdsa_sk_webauthn.pub", "ecdsa_sk_webauthn.sig",
+ msg, namespace);
+ TEST_DONE();
+#endif
+
+ sshbuf_free(msg);
+ free(namespace);
+}
diff --git a/regress/unittests/sshsig/webauthn.html b/regress/unittests/sshsig/webauthn.html
new file mode 100644
index 000000000..1869c8b37
--- /dev/null
+++ b/regress/unittests/sshsig/webauthn.html
@@ -0,0 +1,766 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>webauthn test</title>
+</head>
+<body onload="init()">
+<h1>webauthn test</h1>
+<p>
+This is a demo/test page for generating FIDO keys and signatures in SSH
+formats. The page initially displays a form to generate a FIDO key and
+convert it to a SSH public key.
+</p>
+<p>
+Once a key has been generated, an additional form will be displayed to
+allow signing of data using the just-generated key. The data may be signed
+as either a raw SSH signature or wrapped in a sshsig message (the latter is
+easier to test using command-line tools.
+</p>
+<p>
+Lots of debugging is printed along the way.
+</p>
+<h2>Enroll</h2>
+<span id="error" style="color: #800; font-weight: bold; font-size: 150%;"></span>
+<form id="enrollform">
+<table>
+<tr>
+<td><b>Username:</b></td>
+<td><input id="username" type="text" size="20" name="user" value="test" /></td>
+</tr>
+<tr><td></td><td><input id="assertsubmit" type="submit" value="submit" /></td></tr>
+</table>
+</form>
+<span id="enrollresult" style="visibility: hidden;">
+<h2>clientData</h2>
+<pre id="enrollresultjson" style="color: #008; font-family: monospace;"></pre>
+<h2>attestationObject raw</h2>
+<pre id="enrollresultraw" style="color: #008; font-family: monospace;"></pre>
+<h2>attestationObject</h2>
+<pre id="enrollresultattestobj" style="color: #008; font-family: monospace;"></pre>
+<h2>key handle</h2>
+<pre id="keyhandle" style="color: #008; font-family: monospace;"></pre>
+<h2>authData raw</h2>
+<pre id="enrollresultauthdataraw" style="color: #008; font-family: monospace;"></pre>
+<h2>authData</h2>
+<pre id="enrollresultauthdata" style="color: #008; font-family: monospace;"></pre>
+<h2>SSH pubkey blob</h2>
+<pre id="enrollresultpkblob" style="color: #008; font-family: monospace;"></pre>
+<h2>SSH pubkey string</h2>
+<pre id="enrollresultpk" style="color: #008; font-family: monospace;"></pre>
+<h2>SSH private key string</h2>
+<pre id="enrollresultprivkey" style="color: #008; font-family: monospace;"></pre>
+</span>
+<span id="assertsection" style="visibility: hidden;">
+<h2>Assert</h2>
+<form id="assertform">
+<span id="asserterror" style="color: #800; font-weight: bold;"></span>
+<table>
+<tr>
+<td><b>Data to sign:</b></td>
+<td><input id="message" type="text" size="20" name="message" value="test" /></td>
+</tr>
+<tr>
+<td><input id="message_sshsig" type="checkbox" checked /> use sshsig format</td>
+</tr>
+<tr>
+<td><b>Signature namespace:</b></td>
+<td><input id="message_namespace" type="text" size="20" name="namespace" value="test" /></td>
+</tr>
+<tr><td></td><td><input type="submit" value="submit" /></td></tr>
+</table>
+</form>
+</span>
+<span id="assertresult" style="visibility: hidden;">
+<h2>clientData</h2>
+<pre id="assertresultjson" style="color: #008; font-family: monospace;"></pre>
+<h2>signature raw</h2>
+<pre id="assertresultsigraw" style="color: #008; font-family: monospace;"></pre>
+<h2>authenticatorData raw</h2>
+<pre id="assertresultauthdataraw" style="color: #008; font-family: monospace;"></pre>
+<h2>authenticatorData</h2>
+<pre id="assertresultauthdata" style="color: #008; font-family: monospace;"></pre>
+<h2>signature in SSH format</h2>
+<pre id="assertresultsshsigraw" style="color: #008; font-family: monospace;"></pre>
+<h2>signature in SSH format (base64 encoded)</h2>
+<pre id="assertresultsshsigb64" style="color: #008; font-family: monospace;"></pre>
+</span>
+</body>
+<script>
+// ------------------------------------------------------------------
+// a crappy CBOR decoder - 20200401 djm@openbsd.org
+
+var CBORDecode = function(buffer) {
+ this.buf = buffer
+ this.v = new DataView(buffer)
+ this.offset = 0
+}
+
+CBORDecode.prototype.empty = function() {
+ return this.offset >= this.buf.byteLength
+}
+
+CBORDecode.prototype.getU8 = function() {
+ let r = this.v.getUint8(this.offset)
+ this.offset += 1
+ return r
+}
+
+CBORDecode.prototype.getU16 = function() {
+ let r = this.v.getUint16(this.offset)
+ this.offset += 2
+ return r
+}
+
+CBORDecode.prototype.getU32 = function() {
+ let r = this.v.getUint32(this.offset)
+ this.offset += 4
+ return r
+}
+
+CBORDecode.prototype.getU64 = function() {
+ let r = this.v.getUint64(this.offset)
+ this.offset += 8
+ return r
+}
+
+CBORDecode.prototype.getCBORTypeLen = function() {
+ let tl, t, l
+ tl = this.getU8()
+ t = (tl & 0xe0) >> 5
+ l = tl & 0x1f
+ return [t, this.decodeInteger(l)]
+}
+
+CBORDecode.prototype.decodeInteger = function(len) {
+ switch (len) {
+ case 0x18: return this.getU8()
+ case 0x19: return this.getU16()
+ case 0x20: return this.getU32()
+ case 0x21: return this.getU64()
+ default:
+ if (len <= 23) {
+ return len
+ }
+ throw new Error("Unsupported int type 0x" + len.toString(16))
+ }
+}
+
+CBORDecode.prototype.decodeNegint = function(len) {
+ let r = -(this.decodeInteger(len) + 1)
+ return r
+}
+
+CBORDecode.prototype.decodeByteString = function(len) {
+ let r = this.buf.slice(this.offset, this.offset + len)
+ this.offset += len
+ return r
+}
+
+CBORDecode.prototype.decodeTextString = function(len) {
+ let u8dec = new TextDecoder('utf-8')
+ r = u8dec.decode(this.decodeByteString(len))
+ return r
+}
+
+CBORDecode.prototype.decodeArray = function(len, level) {
+ let r = []
+ for (let i = 0; i < len; i++) {
+ let v = this.decodeInternal(level)
+ r.push(v)
+ // console.log("decodeArray level " + level.toString() + " index " + i.toString() + " value " + JSON.stringify(v))
+ }
+ return r
+}
+
+CBORDecode.prototype.decodeMap = function(len, level) {
+ let r = {}
+ for (let i = 0; i < len; i++) {
+ let k = this.decodeInternal(level)
+ let v = this.decodeInternal(level)
+ r[k] = v
+ // console.log("decodeMap level " + level.toString() + " key " + k.toString() + " value " + JSON.stringify(v))
+ // XXX check string keys, duplicates
+ }
+ return r
+}
+
+CBORDecode.prototype.decodePrimitive = function(t) {
+ switch (t) {
+ case 20: return false
+ case 21: return true
+ case 22: return null
+ case 23: return undefined
+ default:
+ throw new Error("Unsupported primitive 0x" + t.toString(2))
+ }
+}
+
+CBORDecode.prototype.decodeInternal = function(level) {
+ if (level > 256) {
+ throw new Error("CBOR nesting too deep")
+ }
+ let t, l, r
+ [t, l] = this.getCBORTypeLen()
+ // console.log("decode level " + level.toString() + " type " + t.toString() + " len " + l.toString())
+ switch (t) {
+ case 0:
+ r = this.decodeInteger(l)
+ break
+ case 1:
+ r = this.decodeNegint(l)
+ break
+ case 2:
+ r = this.decodeByteString(l)
+ break
+ case 3:
+ r = this.decodeTextString(l)
+ break
+ case 4:
+ r = this.decodeArray(l, level + 1)
+ break
+ case 5:
+ r = this.decodeMap(l, level + 1)
+ break
+ case 6:
+ console.log("XXX ignored semantic tag " + this.decodeInteger(l).toString())
+ break;
+ case 7:
+ r = this.decodePrimitive(l)
+ break
+ default:
+ throw new Error("Unsupported type 0x" + t.toString(2) + " len " + l.toString())
+ }
+ // console.log("decode level " + level.toString() + " value " + JSON.stringify(r))
+ return r
+}
+
+CBORDecode.prototype.decode = function() {
+ return this.decodeInternal(0)
+}
+
+// ------------------------------------------------------------------
+// a crappy SSH message packer - 20200401 djm@openbsd.org
+
+var SSHMSG = function() {
+ this.r = []
+}
+
+SSHMSG.prototype.length = function() {
+ let len = 0
+ for (buf of this.r) {
+ len += buf.length
+ }
+ return len
+}
+
+SSHMSG.prototype.serialise = function() {
+ let r = new ArrayBuffer(this.length())
+ let v = new Uint8Array(r)
+ let offset = 0
+ for (buf of this.r) {
+ v.set(buf, offset)
+ offset += buf.length
+ }
+ if (offset != r.byteLength) {
+ throw new Error("djm can't count")
+ }
+ return r
+}
+
+SSHMSG.prototype.serialiseBase64 = function(v) {
+ let b = this.serialise()
+ return btoa(String.fromCharCode(...new Uint8Array(b)));
+}
+
+SSHMSG.prototype.putU8 = function(v) {
+ this.r.push(new Uint8Array([v]))
+}
+
+SSHMSG.prototype.putU32 = function(v) {
+ this.r.push(new Uint8Array([
+ (v >> 24) & 0xff,
+ (v >> 16) & 0xff,
+ (v >> 8) & 0xff,
+ (v & 0xff)
+ ]))
+}
+
+SSHMSG.prototype.put = function(v) {
+ this.r.push(new Uint8Array(v))
+}
+
+SSHMSG.prototype.putStringRaw = function(v) {
+ let enc = new TextEncoder();
+ let venc = enc.encode(v)
+ this.put(venc)
+}
+
+SSHMSG.prototype.putString = function(v) {
+ let enc = new TextEncoder();
+ let venc = enc.encode(v)
+ this.putU32(venc.length)
+ this.put(venc)
+}
+
+SSHMSG.prototype.putSSHMSG = function(v) {
+ let msg = v.serialise()
+ this.putU32(msg.byteLength)
+ this.put(msg)
+}
+
+SSHMSG.prototype.putBytes = function(v) {
+ this.putU32(v.byteLength)
+ this.put(v)
+}
+
+SSHMSG.prototype.putECPoint = function(x, y) {
+ let x8 = new Uint8Array(x)
+ let y8 = new Uint8Array(y)
+ this.putU32(1 + x8.length + y8.length)
+ this.putU8(0x04) // Uncompressed point format.
+ this.put(x8)
+ this.put(y8)
+}
+
+// ------------------------------------------------------------------
+// webauthn to SSH glue - djm@openbsd.org 20200408
+
+function error(msg, ...args) {
+ document.getElementById("error").innerText = msg
+ console.log(msg)
+ for (const arg of args) {
+ console.dir(arg)
+ }
+}
+function hexdump(buf) {
+ const hex = Array.from(new Uint8Array(buf)).map(
+ b => b.toString(16).padStart(2, "0"))
+ const fmt = new Array()
+ for (let i = 0; i < hex.length; i++) {
+ if ((i % 16) == 0) {
+ // Prepend length every 16 bytes.
+ fmt.push(i.toString(16).padStart(4, "0"))
+ fmt.push(" ")
+ }
+ fmt.push(hex[i])
+ fmt.push(" ")
+ if ((i % 16) == 15) {
+ fmt.push("\n")
+ }
+ }
+ return fmt.join("")
+}
+function enrollform_submit(event) {
+ event.preventDefault();
+ console.log("submitted")
+ username = event.target.elements.username.value
+ if (username === "") {
+ error("no username specified")
+ return false
+ }
+ enrollStart(username)
+}
+function enrollStart(username) {
+ let challenge = new Uint8Array(32)
+ window.crypto.getRandomValues(challenge)
+ let userid = new Uint8Array(8)
+ window.crypto.getRandomValues(userid)
+
+ console.log("challenge:" + btoa(challenge))
+ console.log("userid:" + btoa(userid))
+
+ let pkopts = {
+ challenge: challenge,
+ rp: {
+ name: "mindrot.org",
+ id: "mindrot.org",
+ },
+ user: {
+ id: userid,
+ name: username,
+ displayName: username,
+ },
+ authenticatorSelection: {
+ authenticatorAttachment: "cross-platform",
+ userVerification: "discouraged",
+ },
+ pubKeyCredParams: [{alg: -7, type: "public-key"}], // ES256
+ timeout: 30 * 1000,
+ };
+ console.dir(pkopts)
+ window.enrollOpts = pkopts
+ let credpromise = navigator.credentials.create({ publicKey: pkopts });
+ credpromise.then(enrollSuccess, enrollFailure)
+}
+function enrollFailure(result) {
+ error("Enroll failed", result)
+}
+function enrollSuccess(result) {
+ console.log("Enroll succeeded")
+ console.dir(result)
+ window.enrollResult = result
+ document.getElementById("enrollresult").style.visibility = "visible"
+
+ // Show the clientData
+ let u8dec = new TextDecoder('utf-8')
+ clientData = u8dec.decode(result.response.clientDataJSON)
+ document.getElementById("enrollresultjson").innerText = clientData
+
+ // Show the raw key handle.
+ document.getElementById("keyhandle").innerText = hexdump(result.rawId)
+
+ // Decode and show the attestationObject
+ document.getElementById("enrollresultraw").innerText = hexdump(result.response.attestationObject)
+ let aod = new CBORDecode(result.response.attestationObject)
+ let attestationObject = aod.decode()
+ console.log("attestationObject")
+ console.dir(attestationObject)
+ document.getElementById("enrollresultattestobj").innerText = JSON.stringify(attestationObject)
+
+ // Decode and show the authData
+ document.getElementById("enrollresultauthdataraw").innerText = hexdump(attestationObject.authData)
+ let authData = decodeAuthenticatorData(attestationObject.authData, true)
+ console.log("authData")
+ console.dir(authData)
+ window.enrollAuthData = authData
+ document.getElementById("enrollresultauthdata").innerText = JSON.stringify(authData)
+
+ // Reformat the pubkey as a SSH key for easy verification
+ window.rawKey = reformatPubkey(authData.attestedCredentialData.credentialPublicKey, window.enrollOpts.rp.id)
+ console.log("SSH pubkey blob")
+ console.dir(window.rawKey)
+ document.getElementById("enrollresultpkblob").innerText = hexdump(window.rawKey)
+ let pk64 = btoa(String.fromCharCode(...new Uint8Array(window.rawKey)));
+ let pk = "sk-ecdsa-sha2-nistp256@openssh.com " + pk64
+ document.getElementById("enrollresultpk").innerText = pk
+
+ // Format a private key too.
+ flags = 0x01 // SSH_SK_USER_PRESENCE_REQD
+ window.rawPrivkey = reformatPrivkey(authData.attestedCredentialData.credentialPublicKey, window.enrollOpts.rp.id, result.rawId, flags)
+ let privkeyFileBlob = privkeyFile(window.rawKey, window.rawPrivkey, window.enrollOpts.user.name, window.enrollOpts.rp.id)
+ let privk64 = btoa(String.fromCharCode(...new Uint8Array(privkeyFileBlob)));
+ let privkey = "-----BEGIN OPENSSH PRIVATE KEY-----\n" + wrapString(privk64, 70) + "-----END OPENSSH PRIVATE KEY-----\n"
+ document.getElementById("enrollresultprivkey").innerText = privkey
+
+ // Success: show the assertion form.
+ document.getElementById("assertsection").style.visibility = "visible"
+}
+
+function decodeAuthenticatorData(authData, expectCred) {
+ let r = new Object()
+ let v = new DataView(authData)
+
+ r.rpIdHash = authData.slice(0, 32)
+ r.flags = v.getUint8(32)
+ r.signCount = v.getUint32(33)
+
+ // Decode attestedCredentialData if present.
+ let offset = 37
+ let acd = new Object()
+ if (expectCred) {
+ acd.aaguid = authData.slice(offset, offset+16)
+ offset += 16
+ let credentialIdLength = v.getUint16(offset)
+ offset += 2
+ acd.credentialIdLength = credentialIdLength
+ acd.credentialId = authData.slice(offset, offset+credentialIdLength)
+ offset += credentialIdLength
+ r.attestedCredentialData = acd
+ }
+ console.log("XXXXX " + offset.toString())
+ let pubkeyrest = authData.slice(offset, authData.byteLength)
+ let pkdecode = new CBORDecode(pubkeyrest)
+ if (expectCred) {
+ // XXX unsafe: doesn't mandate COSE canonical format.
+ acd.credentialPublicKey = pkdecode.decode()
+ }
+ if (!pkdecode.empty()) {
+ // Decode extensions if present.
+ r.extensions = pkdecode.decode()
+ }
+ return r
+}
+
+function wrapString(s, l) {
+ ret = ""
+ for (i = 0; i < s.length; i += l) {
+ ret += s.slice(i, i + l) + "\n"
+ }
+ return ret
+}
+
+function checkPubkey(pk) {
+ // pk is in COSE format. We only care about a tiny subset.
+ if (pk[1] != 2) {
+ console.dir(pk)
+ throw new Error("pubkey is not EC")
+ }
+ if (pk[-1] != 1) {
+ throw new Error("pubkey is not in P256")
+ }
+ if (pk[3] != -7) {
+ throw new Error("pubkey is not ES256")
+ }
+ if (pk[-2].byteLength != 32 || pk[-3].byteLength != 32) {
+ throw new Error("pubkey EC coords have bad length")
+ }
+}
+
+function reformatPubkey(pk, rpid) {
+ checkPubkey(pk)
+ let msg = new SSHMSG()
+ msg.putString("sk-ecdsa-sha2-nistp256@openssh.com") // Key type
+ msg.putString("nistp256") // Key curve
+ msg.putECPoint(pk[-2], pk[-3]) // EC key
+ msg.putString(rpid) // RP ID
+ return msg.serialise()
+}
+
+function reformatPrivkey(pk, rpid, kh, flags) {
+ checkPubkey(pk)
+ let msg = new SSHMSG()
+ msg.putString("sk-ecdsa-sha2-nistp256@openssh.com") // Key type
+ msg.putString("nistp256") // Key curve
+ msg.putECPoint(pk[-2], pk[-3]) // EC key
+ msg.putString(rpid) // RP ID
+ msg.putU8(flags) // flags
+ msg.putBytes(kh) // handle
+ msg.putString("") // reserved
+ return msg.serialise()
+}
+
+function privkeyFile(pub, priv, user, rp) {
+ let innerMsg = new SSHMSG()
+ innerMsg.putU32(0xdeadbeef) // check byte
+ innerMsg.putU32(0xdeadbeef) // check byte
+ innerMsg.put(priv) // privkey
+ innerMsg.putString("webauthn.html " + user + "@" + rp) // comment
+ // Pad to cipher blocksize (8).
+ p = 1
+ while (innerMsg.length() % 8 != 0) {
+ innerMsg.putU8(p++)
+ }
+ let msg = new SSHMSG()
+ msg.putStringRaw("openssh-key-v1") // Magic
+ msg.putU8(0) // \0 terminate
+ msg.putString("none") // cipher
+ msg.putString("none") // KDF
+ msg.putString("") // KDF options
+ msg.putU32(1) // nkeys
+ msg.putBytes(pub) // pubkey
+ msg.putSSHMSG(innerMsg) // inner
+ //msg.put(innerMsg.serialise()) // inner
+ return msg.serialise()
+}
+
+async function assertform_submit(event) {
+ event.preventDefault();
+ console.log("submitted")
+ message = event.target.elements.message.value
+ if (message === "") {
+ error("no message specified")
+ return false
+ }
+ let enc = new TextEncoder()
+ let encmsg = enc.encode(message)
+ window.assertSignRaw = !event.target.elements.message_sshsig.checked
+ console.log("using sshsig ", !window.assertSignRaw)
+ if (window.assertSignRaw) {
+ assertStart(encmsg)
+ return
+ }
+ // Format a sshsig-style message.
+ window.sigHashAlg = "sha512"
+ let msghash = await crypto.subtle.digest("SHA-512", encmsg);
+ console.log("raw message hash")
+ console.dir(msghash)
+ window.sigNamespace = event.target.elements.message_namespace.value
+ let sigbuf = new SSHMSG()
+ sigbuf.put(enc.encode("SSHSIG"))
+ sigbuf.putString(window.sigNamespace)
+ sigbuf.putU32(0) // Reserved string
+ sigbuf.putString(window.sigHashAlg)
+ sigbuf.putBytes(msghash)
+ let msg = sigbuf.serialise()
+ console.log("sigbuf")
+ console.dir(msg)
+ assertStart(msg)
+}
+
+function assertStart(message) {
+ let assertReqOpts = {
+ challenge: message,
+ rpId: "mindrot.org",
+ allowCredentials: [{
+ type: 'public-key',
+ id: window.enrollResult.rawId,
+ }],
+ userVerification: "discouraged",
+ timeout: (30 * 1000),
+ }
+ console.log("assertReqOpts")
+ console.dir(assertReqOpts)
+ window.assertReqOpts = assertReqOpts
+ let assertpromise = navigator.credentials.get({
+ publicKey: assertReqOpts
+ });
+ assertpromise.then(assertSuccess, assertFailure)
+}
+function assertFailure(result) {
+ error("Assertion failed", result)
+}
+function linewrap(s) {
+ const linelen = 70
+ let ret = ""
+ for (let i = 0; i < s.length; i += linelen) {
+ end = i + linelen
+ if (end > s.length) {
+ end = s.length
+ }
+ if (i > 0) {
+ ret += "\n"
+ }
+ ret += s.slice(i, end)
+ }
+ return ret + "\n"
+}
+function assertSuccess(result) {
+ console.log("Assertion succeeded")
+ console.dir(result)
+ window.assertResult = result
+ document.getElementById("assertresult").style.visibility = "visible"
+
+ // show the clientData.
+ let u8dec = new TextDecoder('utf-8')
+ clientData = u8dec.decode(result.response.clientDataJSON)
+ document.getElementById("assertresultjson").innerText = clientData
+
+ // show the signature.
+ document.getElementById("assertresultsigraw").innerText = hexdump(result.response.signature)
+
+ // decode and show the authData.
+ document.getElementById("assertresultauthdataraw").innerText = hexdump(result.response.authenticatorData)
+ authData = decodeAuthenticatorData(result.response.authenticatorData, false)
+ document.getElementById("assertresultauthdata").innerText = JSON.stringify(authData)
+
+ // Parse and reformat the signature to an SSH style signature.
+ let sshsig = reformatSignature(result.response.signature, clientData, authData)
+ document.getElementById("assertresultsshsigraw").innerText = hexdump(sshsig)
+ let sig64 = btoa(String.fromCharCode(...new Uint8Array(sshsig)));
+ if (window.assertSignRaw) {
+ document.getElementById("assertresultsshsigb64").innerText = sig64
+ } else {
+ document.getElementById("assertresultsshsigb64").innerText =
+ "-----BEGIN SSH SIGNATURE-----\n" + linewrap(sig64) +
+ "-----END SSH SIGNATURE-----\n";
+ }
+}
+
+function reformatSignature(sig, clientData, authData) {
+ if (sig.byteLength < 2) {
+ throw new Error("signature is too short")
+ }
+ let offset = 0
+ let v = new DataView(sig)
+ // Expect an ASN.1 SEQUENCE that exactly spans the signature.
+ if (v.getUint8(offset) != 0x30) {
+ throw new Error("signature not an ASN.1 sequence")
+ }
+ offset++
+ let seqlen = v.getUint8(offset)
+ offset++
+ if ((seqlen & 0x80) != 0 || seqlen != sig.byteLength - offset) {
+ throw new Error("signature has unexpected length " + seqlen.toString() + " vs expected " + (sig.byteLength - offset).toString())
+ }
+
+ // Parse 'r' INTEGER value.
+ if (v.getUint8(offset) != 0x02) {
+ throw new Error("signature r not an ASN.1 integer")
+ }
+ offset++
+ let rlen = v.getUint8(offset)
+ offset++
+ if ((rlen & 0x80) != 0 || rlen > sig.byteLength - offset) {
+ throw new Error("signature r has unexpected length " + rlen.toString() + " vs buffer " + (sig.byteLength - offset).toString())
+ }
+ let r = sig.slice(offset, offset + rlen)
+ offset += rlen
+ console.log("sig_r")
+ console.dir(r)
+
+ // Parse 's' INTEGER value.
+ if (v.getUint8(offset) != 0x02) {
+ throw new Error("signature r not an ASN.1 integer")
+ }
+ offset++
+ let slen = v.getUint8(offset)
+ offset++
+ if ((slen & 0x80) != 0 || slen > sig.byteLength - offset) {
+ throw new Error("signature s has unexpected length " + slen.toString() + " vs buffer " + (sig.byteLength - offset).toString())
+ }
+ let s = sig.slice(offset, offset + slen)
+ console.log("sig_s")
+ console.dir(s)
+ offset += slen
+
+ if (offset != sig.byteLength) {
+ throw new Error("unexpected final offset during signature parsing " + offset.toString() + " expected " + sig.byteLength.toString())
+ }
+
+ // Reformat as an SSH signature.
+ let clientDataParsed = JSON.parse(clientData)
+ let innersig = new SSHMSG()
+ innersig.putBytes(r)
+ innersig.putBytes(s)
+
+ let rawsshsig = new SSHMSG()
+ rawsshsig.putString("webauthn-sk-ecdsa-sha2-nistp256@openssh.com")
+ rawsshsig.putSSHMSG(innersig)
+ rawsshsig.putU8(authData.flags)
+ rawsshsig.putU32(authData.signCount)
+ rawsshsig.putString(clientDataParsed.origin)
+ rawsshsig.putString(clientData)
+ if (authData.extensions == undefined) {
+ rawsshsig.putU32(0)
+ } else {
+ rawsshsig.putBytes(authData.extensions)
+ }
+
+ if (window.assertSignRaw) {
+ return rawsshsig.serialise()
+ }
+ // Format as SSHSIG.
+ let enc = new TextEncoder()
+ let sshsig = new SSHMSG()
+ sshsig.put(enc.encode("SSHSIG"))
+ sshsig.putU32(0x01) // Signature version.
+ sshsig.putBytes(window.rawKey)
+ sshsig.putString(window.sigNamespace)
+ sshsig.putU32(0) // Reserved string
+ sshsig.putString(window.sigHashAlg)
+ sshsig.putBytes(rawsshsig.serialise())
+ return sshsig.serialise()
+}
+
+function toggleNamespaceVisibility() {
+ const assertsigtype = document.getElementById('message_sshsig');
+ const assertsignamespace = document.getElementById('message_namespace');
+ assertsignamespace.disabled = !assertsigtype.checked;
+}
+
+function init() {
+ if (document.location.protocol != "https:") {
+ error("This page must be loaded via https")
+ const assertsubmit = document.getElementById('assertsubmit')
+ assertsubmit.disabled = true
+ }
+ const enrollform = document.getElementById('enrollform');
+ enrollform.addEventListener('submit', enrollform_submit);
+ const assertform = document.getElementById('assertform');
+ assertform.addEventListener('submit', assertform_submit);
+ const assertsigtype = document.getElementById('message_sshsig');
+ assertsigtype.onclick = toggleNamespaceVisibility;
+}
+</script>
+
+</html>
diff --git a/regress/valgrind-unit.sh b/regress/valgrind-unit.sh
index 4143ead4b..193289e6b 100755
--- a/regress/valgrind-unit.sh
+++ b/regress/valgrind-unit.sh
@@ -19,4 +19,6 @@ if [ "x$VALGRIND_PATH" != "x" ]; then
VG_PATH="$VALGRIND_PATH"
fi
+mkdir -p "$OBJ/valgrind-out"
+
exec $VG_PATH $VG_OPTS $UNIT_BINARY $UNIT_ARGS
diff --git a/sandbox-pledge.c b/sandbox-pledge.c
index d28fc2727..302f1cfed 100644
--- a/sandbox-pledge.c
+++ b/sandbox-pledge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sandbox-pledge.c,v 1.1 2015/10/09 01:37:08 deraadt Exp $ */
+/* $OpenBSD: sandbox-pledge.c,v 1.2 2020/10/18 11:32:01 djm Exp $ */
/*
* Copyright (c) 2015 Theo de Raadt <deraadt@openbsd.org>
*
@@ -46,7 +46,7 @@ ssh_sandbox_init(struct monitor *m)
{
struct ssh_sandbox *box;
- debug3("%s: preparing pledge sandbox", __func__);
+ debug3_f("preparing pledge sandbox");
box = xcalloc(1, sizeof(*box));
box->child_pid = 0;
@@ -57,14 +57,14 @@ void
ssh_sandbox_child(struct ssh_sandbox *box)
{
if (pledge("stdio", NULL) == -1)
- fatal("%s: pledge()", __func__);
+ fatal_f("pledge()");
}
void
ssh_sandbox_parent_finish(struct ssh_sandbox *box)
{
free(box);
- debug3("%s: finished", __func__);
+ debug3_f("finished");
}
void
diff --git a/sandbox-rlimit.c b/sandbox-rlimit.c
index 0bff3dfba..26c61d264 100644
--- a/sandbox-rlimit.c
+++ b/sandbox-rlimit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sandbox-rlimit.c,v 1.4 2016/09/12 01:22:38 deraadt Exp $ */
+/* $OpenBSD: sandbox-rlimit.c,v 1.5 2020/10/18 11:32:01 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller <djm@mindrot.org>
*
@@ -49,7 +49,7 @@ ssh_sandbox_init(struct monitor *monitor)
* Strictly, we don't need to maintain any state here but we need
* to return non-NULL to satisfy the API.
*/
- debug3("%s: preparing rlimit sandbox", __func__);
+ debug3_f("preparing rlimit sandbox");
box = xcalloc(1, sizeof(*box));
box->child_pid = 0;
@@ -65,18 +65,18 @@ ssh_sandbox_child(struct ssh_sandbox *box)
#ifndef SANDBOX_SKIP_RLIMIT_FSIZE
if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1)
- fatal("%s: setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s",
- __func__, strerror(errno));
+ fatal_f("setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s",
+ strerror(errno));
#endif
#ifndef SANDBOX_SKIP_RLIMIT_NOFILE
if (setrlimit(RLIMIT_NOFILE, &rl_zero) == -1)
- fatal("%s: setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s",
- __func__, strerror(errno));
+ fatal_f("setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s",
+ strerror(errno));
#endif
#ifdef HAVE_RLIMIT_NPROC
if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1)
- fatal("%s: setrlimit(RLIMIT_NPROC, { 0, 0 }): %s",
- __func__, strerror(errno));
+ fatal_f("setrlimit(RLIMIT_NPROC, { 0, 0 }): %s",
+ strerror(errno));
#endif
}
@@ -84,7 +84,7 @@ void
ssh_sandbox_parent_finish(struct ssh_sandbox *box)
{
free(box);
- debug3("%s: finished", __func__);
+ debug3_f("finished");
}
void
diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c
index e0768c063..798b24bd8 100644
--- a/sandbox-seccomp-filter.c
+++ b/sandbox-seccomp-filter.c
@@ -154,6 +154,9 @@ static const struct sock_filter preauth_insns[] = {
#ifdef __NR_fstat64
SC_DENY(__NR_fstat64, EACCES),
#endif
+#ifdef __NR_fstatat64
+ SC_DENY(__NR_fstatat64, EACCES),
+#endif
#ifdef __NR_open
SC_DENY(__NR_open, EACCES),
#endif
@@ -181,6 +184,9 @@ static const struct sock_filter preauth_insns[] = {
#ifdef __NR_ipc
SC_DENY(__NR_ipc, EACCES),
#endif
+#ifdef __NR_statx
+ SC_DENY(__NR_statx, EACCES),
+#endif
/* Syscalls to permit */
#ifdef __NR_brk
@@ -204,6 +210,9 @@ static const struct sock_filter preauth_insns[] = {
#ifdef __NR_futex
SC_ALLOW(__NR_futex),
#endif
+#ifdef __NR_futex_time64
+ SC_ALLOW(__NR_futex_time64),
+#endif
#ifdef __NR_geteuid
SC_ALLOW(__NR_geteuid),
#endif
@@ -267,6 +276,9 @@ static const struct sock_filter preauth_insns[] = {
#ifdef __NR_pselect6
SC_ALLOW(__NR_pselect6),
#endif
+#ifdef __NR_pselect6_time64
+ SC_ALLOW(__NR_pselect6_time64),
+#endif
#ifdef __NR_read
SC_ALLOW(__NR_read),
#endif
@@ -372,7 +384,7 @@ ssh_sandbox_child_debugging(void)
fatal("%s: sigaction(SIGSYS): %s", __func__, strerror(errno));
if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1)
fatal("%s: sigprocmask(SIGSYS): %s",
- __func__, strerror(errno));
+ __func__, strerror(errno));
}
#endif /* SANDBOX_SECCOMP_FILTER_DEBUG */
@@ -401,13 +413,13 @@ ssh_sandbox_child(struct ssh_sandbox *box)
debug3("%s: setting PR_SET_NO_NEW_PRIVS", __func__);
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) {
debug("%s: prctl(PR_SET_NO_NEW_PRIVS): %s",
- __func__, strerror(errno));
+ __func__, strerror(errno));
nnp_failed = 1;
}
debug3("%s: attaching seccomp filter program", __func__);
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &preauth_program) == -1)
debug("%s: prctl(PR_SET_SECCOMP): %s",
- __func__, strerror(errno));
+ __func__, strerror(errno));
else if (nnp_failed)
fatal("%s: SECCOMP_MODE_FILTER activated but "
"PR_SET_NO_NEW_PRIVS failed", __func__);
diff --git a/scp.1 b/scp.1
index d5f65af4e..10cd4efb9 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.89 2020/04/30 18:28:37 jmc Exp $
+.\" $OpenBSD: scp.1,v 1.105 2021/09/20 06:53:56 djm Exp $
.\"
-.Dd $Mdocdate: April 30 2020 $
+.Dd $Mdocdate: September 20 2021 $
.Dt SCP 1
.Os
.Sh NAME
@@ -18,8 +18,9 @@
.Nd OpenSSH secure file copy
.Sh SYNOPSIS
.Nm scp
-.Op Fl 346BCpqrTv
+.Op Fl 346ABCOpqRrsTv
.Op Fl c Ar cipher
+.Op Fl D Ar sftp_server_path
.Op Fl F Ar ssh_config
.Op Fl i Ar identity_file
.Op Fl J Ar destination
@@ -31,11 +32,12 @@
.Sh DESCRIPTION
.Nm
copies files between hosts on a network.
+.Pp
It uses
.Xr ssh 1
for data transfer, and uses the same authentication and provides the
-same security as
-.Xr ssh 1 .
+same security as a login session.
+.Pp
.Nm
will ask for passwords or passphrases if they are needed for
authentication.
@@ -62,10 +64,10 @@ as host specifiers.
.Pp
When copying between two remote hosts, if the URI format is used, a
.Ar port
-may only be specified on the
+cannot be specified on the
.Ar target
if the
-.Fl 3
+.Fl R
option is used.
.Pp
The options are as follows:
@@ -74,10 +76,11 @@ The options are as follows:
Copies between two remote hosts are transferred through the local host.
Without this option the data is copied directly between the two remote
hosts.
-Note that this option disables the progress meter and selects batch mode
-for the second host, since
+Note that, when using the original SCP protocol (the default), 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
@@ -86,6 +89,11 @@ to use IPv4 addresses only.
Forces
.Nm
to use IPv6 addresses only.
+.It Fl A
+Allows forwarding of
+.Xr ssh-agent 1
+to the remote system.
+The default is not to forward an authentication agent.
.It Fl B
Selects batch mode (prevents asking for passwords or passphrases).
.It Fl C
@@ -99,6 +107,13 @@ to enable compression.
Selects the cipher to use for encrypting the data transfer.
This option is directly passed to
.Xr ssh 1 .
+.It Fl D Ar sftp_server_path
+When using the SFTP protocol support via
+.Fl s ,
+connect directly to a local SFTP server program rather than a
+remote one via
+.Xr ssh 1 .
+This option may be useful in debugging the client and server.
.It Fl F Ar ssh_config
Specifies an alternative
per-user configuration file for
@@ -125,6 +140,14 @@ This option is directly passed to
.Xr ssh 1 .
.It Fl l Ar limit
Limits the used bandwidth, specified in Kbit/s.
+.It Fl O
+Use the original SCP protocol for file transfers instead of the SFTP protocol.
+Forcing the use of the SCP protocol may be necessary for servers that do
+not implement SFTP, for backwards-compatibility for particular filename
+wildcard patterns and for expanding paths with a
+.Sq ~
+prefix for older SFTP servers.
+This mode is the default.
.It Fl o Ar ssh_option
Can be used to pass options to
.Nm ssh
@@ -149,7 +172,6 @@ For full details of the options listed below, and their possible values, see
.It CanonicalizePermittedCNAMEs
.It CASignatureAlgorithms
.It CertificateFile
-.It ChallengeResponseAuthentication
.It CheckHostIP
.It Ciphers
.It Compression
@@ -163,8 +185,8 @@ For full details of the options listed below, and their possible values, see
.It GSSAPIDelegateCredentials
.It HashKnownHosts
.It Host
+.It HostbasedAcceptedAlgorithms
.It HostbasedAuthentication
-.It HostbasedKeyTypes
.It HostKeyAlgorithms
.It HostKeyAlias
.It Hostname
@@ -175,6 +197,7 @@ For full details of the options listed below, and their possible values, see
.It KbdInteractiveAuthentication
.It KbdInteractiveDevices
.It KexAlgorithms
+.It KnownHostsCommand
.It LogLevel
.It MACs
.It NoHostAuthenticationForLocalhost
@@ -185,7 +208,7 @@ For full details of the options listed below, and their possible values, see
.It PreferredAuthentications
.It ProxyCommand
.It ProxyJump
-.It PubkeyAcceptedKeyTypes
+.It PubkeyAcceptedAlgorithms
.It PubkeyAuthentication
.It RekeyLimit
.It SendEnv
@@ -205,14 +228,23 @@ Note that this option is written with a capital
.Sq P ,
because
.Fl p
-is already reserved for preserving the times and modes of the file.
+is already reserved for preserving the times and mode bits of the file.
.It Fl p
-Preserves modification times, access times, and modes from the
-original file.
+Preserves modification times, access times, and file mode bits from the
+source file.
.It Fl q
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
+host and executing
+.Nm
+there.
+This requires that
+.Nm
+running on the origin host can authenticate to the destination host without
+requiring a password.
.It Fl r
Recursively copy entire directories.
Note that
@@ -225,6 +257,8 @@ to use for the encrypted connection.
The program must understand
.Xr ssh 1
options.
+.It Fl s
+Use the SFTP protocol for transfers rather than the original scp protocol.
.It Fl T
Disable strict filename checking.
By default when copying files from a remote host to a local directory
@@ -254,6 +288,7 @@ debugging connection, authentication, and configuration problems.
.Xr ssh-agent 1 ,
.Xr ssh-keygen 1 ,
.Xr ssh_config 5 ,
+.Xr sftp-server 8 ,
.Xr sshd 8
.Sh HISTORY
.Nm
@@ -263,3 +298,10 @@ source code from the Regents of the University of California.
.Sh AUTHORS
.An Timo Rinne Aq Mt tri@iki.fi
.An Tatu Ylonen Aq Mt ylo@cs.hut.fi
+.Sh CAVEATS
+The original SCP protocol (used by default) requires execution of the
+remote user's shell to perform
+.Xr glob 3
+pattern matching.
+This requires careful quoting of any characters that have special meaning to
+the remote shell, such as quote characters.
diff --git a/scp.c b/scp.c
index b4492a062..73ce8554d 100644
--- a/scp.c
+++ b/scp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scp.c,v 1.210 2020/05/06 20:57:38 djm Exp $ */
+/* $OpenBSD: scp.c,v 1.239 2021/09/20 06:53:56 djm Exp $ */
/*
* scp - secure remote copy. This is basically patched BSD rcp which
* uses ssh to do the data transfer (instead of using rcmd).
@@ -97,6 +97,14 @@
#ifdef HAVE_FNMATCH_H
#include <fnmatch.h>
#endif
+#ifdef USE_SYSTEM_GLOB
+# include <glob.h>
+#else
+# include "openbsd-compat/glob.h"
+#endif
+#ifdef HAVE_LIBGEN_H
+#include <libgen.h>
+#endif
#include <limits.h>
#include <locale.h>
#include <pwd.h>
@@ -123,12 +131,15 @@
#include "progressmeter.h"
#include "utf8.h"
+#include "sftp-common.h"
+#include "sftp-client.h"
+
extern char *__progname;
#define COPY_BUFLEN 16384
-int do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout);
-int do_cmd2(char *host, char *remuser, int port, char *cmd, int fdin, int fdout);
+int do_cmd(char *, char *, char *, int, int, char *, int *, int *, pid_t *);
+int do_cmd2(char *, char *, int, char *, int, int);
/* Struct for addargs */
arglist args;
@@ -143,6 +154,7 @@ char *curfile;
/* This is set to non-zero to enable verbose mode. */
int verbose_mode = 0;
+LogLevel log_level = SYSLOG_LEVEL_INFO;
/* This is set to zero if the progressmeter is not desired. */
int showprogress = 1;
@@ -151,7 +163,7 @@ int showprogress = 1;
* This is set to non-zero if remote-remote copy should be piped
* through this process.
*/
-int throughlocal = 0;
+int throughlocal = 1;
/* Non-standard port to use for the ssh connection or -1. */
int sshport = -1;
@@ -161,6 +173,13 @@ char *ssh_program = _PATH_SSH_PROGRAM;
/* This is used to store the pid of ssh_program */
pid_t do_cmd_pid = -1;
+pid_t do_cmd_pid2 = -1;
+
+/* Needed for sftp */
+volatile sig_atomic_t interrupted = 0;
+
+int remote_glob(struct sftp_conn *, const char *, int,
+ int (*)(const char *, int), glob_t *); /* proto for sftp-glob.c */
static void
killchild(int signo)
@@ -169,6 +188,10 @@ killchild(int signo)
kill(do_cmd_pid, signo ? signo : SIGTERM);
waitpid(do_cmd_pid, NULL, 0);
}
+ if (do_cmd_pid2 > 1) {
+ kill(do_cmd_pid2, signo ? signo : SIGTERM);
+ waitpid(do_cmd_pid2, NULL, 0);
+ }
if (signo)
_exit(1);
@@ -176,19 +199,26 @@ killchild(int signo)
}
static void
-suspchild(int signo)
+suspone(int pid, int signo)
{
int status;
- if (do_cmd_pid > 1) {
- kill(do_cmd_pid, signo);
- while (waitpid(do_cmd_pid, &status, WUNTRACED) == -1 &&
+ if (pid > 1) {
+ kill(pid, signo);
+ while (waitpid(pid, &status, WUNTRACED) == -1 &&
errno == EINTR)
;
- kill(getpid(), SIGSTOP);
}
}
+static void
+suspchild(int signo)
+{
+ suspone(do_cmd_pid, signo);
+ suspone(do_cmd_pid2, signo);
+ kill(getpid(), SIGSTOP);
+}
+
static int
do_local_cmd(arglist *a)
{
@@ -238,14 +268,15 @@ do_local_cmd(arglist *a)
*/
int
-do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout)
+do_cmd(char *program, char *host, char *remuser, int port, int subsystem,
+ char *cmd, int *fdin, int *fdout, pid_t *pid)
{
int pin[2], pout[2], reserved[2];
if (verbose_mode)
fmprintf(stderr,
"Executing: program %s host %s, user %s, command %s\n",
- ssh_program, host,
+ program, host,
remuser ? remuser : "(unspecified)", cmd);
if (port == -1)
@@ -273,8 +304,8 @@ do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout)
ssh_signal(SIGTTOU, suspchild);
/* Fork a child to execute the command on the remote host using ssh. */
- do_cmd_pid = fork();
- if (do_cmd_pid == 0) {
+ *pid = fork();
+ if (*pid == 0) {
/* Child. */
close(pin[1]);
close(pout[0]);
@@ -283,7 +314,7 @@ do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout)
close(pin[0]);
close(pout[1]);
- replacearg(&args, 0, "%s", ssh_program);
+ replacearg(&args, 0, "%s", program);
if (port != -1) {
addargs(&args, "-p");
addargs(&args, "%d", port);
@@ -292,14 +323,16 @@ do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout)
addargs(&args, "-l");
addargs(&args, "%s", remuser);
}
+ if (subsystem)
+ addargs(&args, "-s");
addargs(&args, "--");
addargs(&args, "%s", host);
addargs(&args, "%s", cmd);
- execvp(ssh_program, args.list);
- perror(ssh_program);
+ execvp(program, args.list);
+ perror(program);
exit(1);
- } else if (do_cmd_pid == -1) {
+ } else if (*pid == -1) {
fatal("fork: %s", strerror(errno));
}
/* Parent. Close the other side, and return the local side. */
@@ -319,10 +352,11 @@ do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout)
* This way the input and output of two commands can be connected.
*/
int
-do_cmd2(char *host, char *remuser, int port, char *cmd, int fdin, int fdout)
+do_cmd2(char *host, char *remuser, int port, char *cmd,
+ int fdin, int fdout)
{
- pid_t pid;
int status;
+ pid_t pid;
if (verbose_mode)
fmprintf(stderr,
@@ -373,34 +407,49 @@ typedef struct {
BUF *allocbuf(BUF *, int, int);
void lostconn(int);
int okname(char *);
-void run_err(const char *,...);
-int note_err(const char *,...);
+void run_err(const char *,...)
+ __attribute__((__format__ (printf, 1, 2)))
+ __attribute__((__nonnull__ (1)));
+int note_err(const char *,...)
+ __attribute__((__format__ (printf, 1, 2)));
void verifydir(char *);
struct passwd *pwd;
uid_t userid;
-int errs, remin, remout;
+int errs, remin, remout, remin2, remout2;
int Tflag, pflag, iamremote, iamrecursive, targetshouldbedirectory;
#define CMDNEEDS 64
char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
+enum scp_mode_e {
+ MODE_SCP,
+ MODE_SFTP
+};
+
int response(void);
void rsource(char *, struct stat *);
void sink(int, char *[], const char *);
void source(int, char *[]);
-void tolocal(int, char *[]);
-void toremote(int, char *[]);
+void tolocal(int, char *[], enum scp_mode_e, char *sftp_direct);
+void toremote(int, char *[], enum scp_mode_e, char *sftp_direct);
void usage(void);
+void source_sftp(int, char *, char *, struct sftp_conn *);
+void sink_sftp(int, char *, const char *, struct sftp_conn *);
+void throughlocal_sftp(struct sftp_conn *, struct sftp_conn *,
+ char *, char *);
+
int
main(int argc, char **argv)
{
int ch, fflag, tflag, status, n;
- char **newargv;
+ char **newargv, *argv0;
const char *errstr;
extern char *optarg;
extern int optind;
+ enum scp_mode_e mode = MODE_SCP;
+ char *sftp_direct = NULL;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
@@ -410,6 +459,7 @@ main(int argc, char **argv)
msetlocale();
/* Copy argv, because we modify it */
+ argv0 = argv[0];
newargv = xcalloc(MAXIMUM(argc + 1, 1), sizeof(*newargv));
for (n = 0; n < argc; n++)
newargv[n] = xstrdup(argv[n]);
@@ -417,12 +467,13 @@ main(int argc, char **argv)
__progname = ssh_get_progname(argv[0]);
+ log_init(argv0, log_level, SYSLOG_FACILITY_USER, 2);
+
memset(&args, '\0', sizeof(args));
memset(&remote_remote_args, '\0', sizeof(remote_remote_args));
args.list = remote_remote_args.list = NULL;
addargs(&args, "%s", ssh_program);
addargs(&args, "-x");
- addargs(&args, "-oForwardAgent=no");
addargs(&args, "-oPermitLocalCommand=no");
addargs(&args, "-oClearAllForwardings=yes");
addargs(&args, "-oRemoteCommand=none");
@@ -430,7 +481,7 @@ main(int argc, char **argv)
fflag = Tflag = tflag = 0;
while ((ch = getopt(argc, argv,
- "dfl:prtTvBCc:i:P:q12346S:o:F:J:")) != -1) {
+ "12346ABCTdfOpqRrstvD:F:J:M:P:S:c:i:l:o:")) != -1) {
switch (ch) {
/* User-visible flags. */
case '1':
@@ -439,15 +490,22 @@ main(int argc, char **argv)
case '2':
/* Ignored */
break;
+ case 'A':
case '4':
case '6':
case 'C':
addargs(&args, "-%c", ch);
addargs(&remote_remote_args, "-%c", ch);
break;
+ case 'D':
+ sftp_direct = optarg;
+ break;
case '3':
throughlocal = 1;
break;
+ case 'R':
+ throughlocal = 0;
+ break;
case 'o':
case 'c':
case 'i':
@@ -458,6 +516,12 @@ main(int argc, char **argv)
addargs(&args, "-%c", ch);
addargs(&args, "%s", optarg);
break;
+ case 'O':
+ mode = MODE_SCP;
+ break;
+ case 's':
+ mode = MODE_SFTP;
+ break;
case 'P':
sshport = a2port(optarg);
if (sshport <= 0)
@@ -487,6 +551,10 @@ main(int argc, char **argv)
case 'v':
addargs(&args, "-v");
addargs(&remote_remote_args, "-v");
+ if (verbose_mode == 0)
+ log_level = SYSLOG_LEVEL_DEBUG1;
+ else if (log_level < SYSLOG_LEVEL_DEBUG3)
+ log_level++;
verbose_mode = 1;
break;
case 'q':
@@ -520,6 +588,14 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
+ log_init(argv0, log_level, SYSLOG_FACILITY_USER, 2);
+
+ /* Do this last because we want the user to be able to override it */
+ addargs(&args, "-oForwardAgent=no");
+
+ if (iamremote)
+ mode = MODE_SCP;
+
if ((pwd = getpwuid(userid = getuid())) == NULL)
fatal("unknown user %u", (u_int) userid);
@@ -566,17 +642,17 @@ main(int argc, char **argv)
(void) ssh_signal(SIGPIPE, lostconn);
if (colon(argv[argc - 1])) /* Dest is remote host. */
- toremote(argc, argv);
+ toremote(argc, argv, mode, sftp_direct);
else {
if (targetshouldbedirectory)
verifydir(argv[argc - 1]);
- tolocal(argc, argv); /* Dest is local host. */
+ tolocal(argc, argv, mode, sftp_direct); /* Dest is local host. */
}
/*
* Finally check the exit status of the ssh process, if one was forked
* and no error has occurred yet
*/
- if (do_cmd_pid != -1 && errs == 0) {
+ if (do_cmd_pid != -1 && (mode == MODE_SFTP || errs == 0)) {
if (remin != -1)
(void) close(remin);
if (remout != -1)
@@ -624,7 +700,7 @@ do_times(int fd, int verb, const struct stat *sb)
static int
parse_scp_uri(const char *uri, char **userp, char **hostp, int *portp,
- char **pathp)
+ char **pathp)
{
int r;
@@ -842,7 +918,7 @@ brace_expand(const char *pattern, char ***patternsp, size_t *npatternsp)
goto fail;
}
if (invalid)
- fatal("%s: invalid brace pattern \"%s\"", __func__, cp);
+ fatal_f("invalid brace pattern \"%s\"", cp);
if (expanded) {
/*
* Current entry expanded to new entries on the
@@ -881,14 +957,34 @@ brace_expand(const char *pattern, char ***patternsp, size_t *npatternsp)
return ret;
}
+static struct sftp_conn *
+do_sftp_connect(char *host, char *user, int port, char *sftp_direct,
+ int *reminp, int *remoutp, int *pidp)
+{
+ if (sftp_direct == NULL) {
+ if (do_cmd(ssh_program, host, user, port, 1, "sftp",
+ reminp, remoutp, pidp) < 0)
+ return NULL;
+
+ } else {
+ args.list = NULL;
+ addargs(&args, "sftp-server");
+ if (do_cmd(sftp_direct, host, NULL, -1, 0, "sftp",
+ reminp, remoutp, pidp) < 0)
+ return NULL;
+ }
+ return do_init(*reminp, *remoutp, 32768, 64, limit_kbps);
+}
+
void
-toremote(int argc, char **argv)
+toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct)
{
char *suser = NULL, *host = NULL, *src = NULL;
char *bp, *tuser, *thost, *targ;
int sport = -1, tport = -1;
+ struct sftp_conn *conn = NULL, *conn2 = NULL;
arglist alist;
- int i, r;
+ int i, r, status;
u_int j;
memset(&alist, '\0', sizeof(alist));
@@ -909,10 +1005,6 @@ toremote(int argc, char **argv)
goto out;
}
}
- if (tuser != NULL && !okname(tuser)) {
- ++errs;
- goto out;
- }
/* Parse source files */
for (i = 0; i < argc - 1; i++) {
@@ -933,24 +1025,77 @@ toremote(int argc, char **argv)
continue;
}
if (host && throughlocal) { /* extended remote to remote */
- xasprintf(&bp, "%s -f %s%s", cmd,
- *src == '-' ? "-- " : "", src);
- if (do_cmd(host, suser, sport, bp, &remin, &remout) < 0)
- exit(1);
- free(bp);
- xasprintf(&bp, "%s -t %s%s", cmd,
- *targ == '-' ? "-- " : "", targ);
- if (do_cmd2(thost, tuser, tport, bp, remin, remout) < 0)
- exit(1);
- free(bp);
- (void) close(remin);
- (void) close(remout);
- remin = remout = -1;
+ if (mode == MODE_SFTP) {
+ if (remin == -1) {
+ /* Connect to dest now */
+ conn = do_sftp_connect(thost, tuser,
+ tport, sftp_direct,
+ &remin, &remout, &do_cmd_pid);
+ if (conn == NULL) {
+ fatal("Unable to open "
+ "destination connection");
+ }
+ debug3_f("origin in %d out %d pid %ld",
+ remin, remout, (long)do_cmd_pid);
+ }
+ /*
+ * XXX remember suser/host/sport and only
+ * reconnect if they change between arguments.
+ * would save reconnections for cases like
+ * scp -3 hosta:/foo hosta:/bar hostb:
+ */
+ /* Connect to origin now */
+ conn2 = do_sftp_connect(host, suser,
+ sport, sftp_direct,
+ &remin2, &remout2, &do_cmd_pid2);
+ if (conn2 == NULL) {
+ fatal("Unable to open "
+ "source connection");
+ }
+ debug3_f("destination in %d out %d pid %ld",
+ remin2, remout2, (long)do_cmd_pid2);
+ throughlocal_sftp(conn2, conn, src, targ);
+ (void) close(remin2);
+ (void) close(remout2);
+ remin2 = remout2 = -1;
+ if (waitpid(do_cmd_pid2, &status, 0) == -1)
+ ++errs;
+ else if (!WIFEXITED(status) ||
+ WEXITSTATUS(status) != 0)
+ ++errs;
+ do_cmd_pid2 = -1;
+ continue;
+ } else {
+ xasprintf(&bp, "%s -f %s%s", cmd,
+ *src == '-' ? "-- " : "", src);
+ if (do_cmd(ssh_program, host, suser, sport, 0,
+ bp, &remin, &remout, &do_cmd_pid) < 0)
+ exit(1);
+ free(bp);
+ xasprintf(&bp, "%s -t %s%s", cmd,
+ *targ == '-' ? "-- " : "", targ);
+ if (do_cmd2(thost, tuser, tport, bp,
+ remin, remout) < 0)
+ exit(1);
+ free(bp);
+ (void) close(remin);
+ (void) close(remout);
+ remin = remout = -1;
+ }
} else if (host) { /* standard remote to remote */
+ /*
+ * Second remote user is passed to first remote side
+ * via scp command-line. Ensure it contains no obvious
+ * shell characters.
+ */
+ if (tuser != NULL && !okname(tuser)) {
+ ++errs;
+ continue;
+ }
if (tport != -1 && tport != SSH_DEFAULT_PORT) {
/* This would require the remote support URIs */
fatal("target port not supported with two "
- "remote hosts without the -3 option");
+ "remote hosts and the -R option");
}
freeargs(&alist);
@@ -981,11 +1126,28 @@ toremote(int argc, char **argv)
if (do_local_cmd(&alist) != 0)
errs = 1;
} else { /* local to remote */
+ if (mode == MODE_SFTP) {
+ if (remin == -1) {
+ /* Connect to remote now */
+ conn = do_sftp_connect(thost, tuser,
+ tport, sftp_direct,
+ &remin, &remout, &do_cmd_pid);
+ if (conn == NULL) {
+ fatal("Unable to open sftp "
+ "connection");
+ }
+ }
+
+ /* The protocol */
+ source_sftp(1, argv[i], targ, conn);
+ continue;
+ }
+ /* SCP */
if (remin == -1) {
xasprintf(&bp, "%s -t %s%s", cmd,
*targ == '-' ? "-- " : "", targ);
- if (do_cmd(thost, tuser, tport, bp, &remin,
- &remout) < 0)
+ if (do_cmd(ssh_program, thost, tuser, tport, 0,
+ bp, &remin, &remout, &do_cmd_pid) < 0)
exit(1);
if (response() < 0)
exit(1);
@@ -995,6 +1157,8 @@ toremote(int argc, char **argv)
}
}
out:
+ if (mode == MODE_SFTP)
+ free(conn);
free(tuser);
free(thost);
free(targ);
@@ -1004,10 +1168,11 @@ out:
}
void
-tolocal(int argc, char **argv)
+tolocal(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct)
{
char *bp, *host = NULL, *src = NULL, *suser = NULL;
arglist alist;
+ struct sftp_conn *conn = NULL;
int i, r, sport = -1;
memset(&alist, '\0', sizeof(alist));
@@ -1044,9 +1209,29 @@ tolocal(int argc, char **argv)
continue;
}
/* Remote to local. */
+ if (mode == MODE_SFTP) {
+ conn = do_sftp_connect(host, suser, sport,
+ sftp_direct, &remin, &remout, &do_cmd_pid);
+ if (conn == NULL) {
+ error("sftp connection failed");
+ ++errs;
+ continue;
+ }
+
+ /* The protocol */
+ sink_sftp(1, argv[argc - 1], src, conn);
+
+ free(conn);
+ (void) close(remin);
+ (void) close(remout);
+ remin = remout = -1;
+ continue;
+ }
+ /* SCP */
xasprintf(&bp, "%s -f %s%s",
cmd, *src == '-' ? "-- " : "", src);
- if (do_cmd(host, suser, sport, bp, &remin, &remout) < 0) {
+ if (do_cmd(ssh_program, host, suser, sport, 0, bp,
+ &remin, &remout, &do_cmd_pid) < 0) {
free(bp);
++errs;
continue;
@@ -1061,6 +1246,69 @@ tolocal(int argc, char **argv)
free(src);
}
+/* Prepare remote path, handling ~ by assuming cwd is the homedir */
+static char *
+prepare_remote_path(struct sftp_conn *conn, const char *path)
+{
+ /* Handle ~ prefixed paths */
+ if (*path != '~')
+ return xstrdup(path);
+ if (*path == '\0' || strcmp(path, "~") == 0)
+ return xstrdup(".");
+ if (strncmp(path, "~/", 2) == 0)
+ return xstrdup(path + 2);
+ if (can_expand_path(conn))
+ return do_expand_path(conn, path);
+ /* No protocol extension */
+ error("server expand-path extension is required "
+ "for ~user paths in SFTP mode");
+ return NULL;
+}
+
+void
+source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn)
+{
+ char *target = NULL, *filename = NULL, *abs_dst = NULL;
+ int target_is_dir;
+
+ if ((filename = basename(src)) == NULL)
+ fatal("basename %s: %s", src, strerror(errno));
+
+ /*
+ * No need to glob here - the local shell already took care of
+ * the expansions
+ */
+ if ((target = prepare_remote_path(conn, targ)) == NULL)
+ cleanup_exit(255);
+ target_is_dir = remote_is_dir(conn, target);
+ if (targetshouldbedirectory && !target_is_dir) {
+ fatal("Target is not a directory, but more files selected "
+ "for upload");
+ }
+ if (target_is_dir)
+ abs_dst = path_append(target, filename);
+ else {
+ abs_dst = target;
+ target = NULL;
+ }
+ debug3_f("copying local %s to remote %s", src, abs_dst);
+
+ if (local_is_dir(src) && iamrecursive) {
+ if (upload_dir(conn, src, abs_dst, pflag,
+ SFTP_PROGRESS_ONLY, 0, 0, 1) != 0) {
+ error("failed to upload directory %s to %s",
+ src, abs_dst);
+ errs = 1;
+ }
+ } else if (do_upload(conn, src, abs_dst, pflag, 0, 0) != 0) {
+ error("failed to upload file %s to %s", src, abs_dst);
+ errs = 1;
+ }
+
+ free(abs_dst);
+ free(target);
+}
+
void
source(int argc, char **argv)
{
@@ -1222,6 +1470,81 @@ rsource(char *name, struct stat *statp)
(void) response();
}
+void
+sink_sftp(int argc, char *dst, const char *src, struct sftp_conn *conn)
+{
+ char *abs_src = NULL;
+ char *abs_dst = NULL;
+ glob_t g;
+ char *filename, *tmp = NULL;
+ int i, r, err = 0;
+
+ memset(&g, 0, sizeof(g));
+ /*
+ * Here, we need remote glob as SFTP can not depend on remote shell
+ * expansions
+ */
+
+ if ((abs_src = prepare_remote_path(conn, src)) == NULL) {
+ err = -1;
+ goto out;
+ }
+
+ debug3_f("copying remote %s to local %s", abs_src, dst);
+ if ((r = remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) != 0) {
+ if (r == GLOB_NOSPACE)
+ error("%s: too many glob matches", abs_src);
+ else
+ error("%s: %s", abs_src, strerror(ENOENT));
+ err = -1;
+ goto out;
+ }
+
+ if (g.gl_matchc > 1 && !local_is_dir(dst)) {
+ error("Multiple files match pattern, but destination "
+ "\"%s\" is not a directory", dst);
+ err = -1;
+ goto out;
+ }
+
+ for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
+ tmp = xstrdup(g.gl_pathv[i]);
+ if ((filename = basename(tmp)) == NULL) {
+ error("basename %s: %s", tmp, strerror(errno));
+ err = -1;
+ goto out;
+ }
+
+ if (local_is_dir(dst))
+ abs_dst = path_append(dst, filename);
+ else
+ abs_dst = xstrdup(dst);
+
+ debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
+ if (globpath_is_dir(g.gl_pathv[i]) && iamrecursive) {
+ if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
+ pflag, SFTP_PROGRESS_ONLY, 0, 0, 1) == -1)
+ err = -1;
+ } else {
+ if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
+ pflag, 0, 0) == -1)
+ err = -1;
+ }
+ free(abs_dst);
+ abs_dst = NULL;
+ free(tmp);
+ tmp = NULL;
+ }
+
+out:
+ free(abs_src);
+ free(tmp);
+ globfree(&g);
+ if (err == -1)
+ errs = 1;
+}
+
+
#define TYPE_OVERFLOW(type, val) \
((sizeof(type) == 4 && (val) > INT32_MAX) || \
(sizeof(type) == 8 && (val) > INT64_MAX) || \
@@ -1273,7 +1596,7 @@ sink(int argc, char **argv, const char *src)
* the requested destination file glob.
*/
if (brace_expand(src, &patterns, &npatterns) != 0)
- fatal("%s: could not expand pattern", __func__);
+ fatal_f("could not expand pattern");
}
for (first = 1;; first = 0) {
cp = buf;
@@ -1417,8 +1740,7 @@ sink(int argc, char **argv, const char *src)
if (pflag)
(void) chmod(np, mode);
} else {
- /* Handle copying from a read-only
- directory */
+ /* Handle copying from a read-only directory */
mod_flag = 1;
if (mkdir(np, mode | S_IRWXU) == -1)
goto bad;
@@ -1520,7 +1842,7 @@ bad: run_err("%s: %s", np, strerror(errno));
}
}
if (close(ofd) == -1)
- note_err(np, "%s: close: %s", np, strerror(errno));
+ note_err("%s: close: %s", np, strerror(errno));
(void) response();
if (showprogress)
stop_progress_meter();
@@ -1548,6 +1870,79 @@ screwup:
exit(1);
}
+void
+throughlocal_sftp(struct sftp_conn *from, struct sftp_conn *to,
+ char *src, char *targ)
+{
+ char *target = NULL, *filename = NULL, *abs_dst = NULL;
+ char *abs_src = NULL, *tmp = NULL;
+ glob_t g;
+ int i, r, targetisdir, err = 0;
+
+ if ((filename = basename(src)) == NULL)
+ fatal("basename %s: %s", src, strerror(errno));
+
+ if ((abs_src = prepare_remote_path(from, src)) == NULL ||
+ (target = prepare_remote_path(to, targ)) == NULL)
+ cleanup_exit(255);
+ memset(&g, 0, sizeof(g));
+
+ targetisdir = remote_is_dir(to, target);
+ if (!targetisdir && targetshouldbedirectory) {
+ error("%s: destination is not a directory", target);
+ err = -1;
+ goto out;
+ }
+
+ debug3_f("copying remote %s to remote %s", abs_src, target);
+ if ((r = remote_glob(from, abs_src, GLOB_MARK, NULL, &g)) != 0) {
+ if (r == GLOB_NOSPACE)
+ error("%s: too many glob matches", abs_src);
+ else
+ error("%s: %s", abs_src, strerror(ENOENT));
+ err = -1;
+ goto out;
+ }
+
+ for (i = 0; g.gl_pathv[i] && !interrupted; i++) {
+ tmp = xstrdup(g.gl_pathv[i]);
+ if ((filename = basename(tmp)) == NULL) {
+ error("basename %s: %s", tmp, strerror(errno));
+ err = -1;
+ goto out;
+ }
+
+ if (targetisdir)
+ abs_dst = path_append(target, filename);
+ else
+ abs_dst = xstrdup(target);
+
+ debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
+ if (globpath_is_dir(g.gl_pathv[i]) && iamrecursive) {
+ if (crossload_dir(from, to, g.gl_pathv[i], abs_dst,
+ NULL, pflag, SFTP_PROGRESS_ONLY, 1) == -1)
+ err = -1;
+ } else {
+ if (do_crossload(from, to, g.gl_pathv[i], abs_dst, NULL,
+ pflag) == -1)
+ err = -1;
+ }
+ free(abs_dst);
+ abs_dst = NULL;
+ free(tmp);
+ tmp = NULL;
+ }
+
+out:
+ free(abs_src);
+ free(abs_dst);
+ free(target);
+ free(tmp);
+ globfree(&g);
+ if (err == -1)
+ errs = 1;
+}
+
int
response(void)
{
@@ -1590,9 +1985,9 @@ void
usage(void)
{
(void) fprintf(stderr,
- "usage: scp [-346BCpqrTv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
- " [-J destination] [-l limit] [-o ssh_option] [-P port]\n"
- " [-S program] source ... target\n");
+ "usage: scp [-346ABCOpqRrsTv] [-c cipher] [-D sftp_server_path] [-F ssh_config]\n"
+ " [-i identity_file] [-J destination] [-l limit]\n"
+ " [-o ssh_option] [-P port] [-S program] source ... target\n");
exit(1);
}
@@ -1731,3 +2126,21 @@ lostconn(int signo)
else
exit(1);
}
+
+void
+cleanup_exit(int i)
+{
+ if (remin > 0)
+ close(remin);
+ if (remout > 0)
+ close(remout);
+ if (remin2 > 0)
+ close(remin2);
+ if (remout2 > 0)
+ close(remout2);
+ if (do_cmd_pid > 0)
+ waitpid(do_cmd_pid, NULL, 0);
+ if (do_cmd_pid2 > 0)
+ waitpid(do_cmd_pid2, NULL, 0);
+ exit(i);
+}
diff --git a/servconf.c b/servconf.c
index f1850312b..e9351b853 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: servconf.c,v 1.363 2020/04/17 03:30:05 djm Exp $ */
+/* $OpenBSD: servconf.c,v 1.382 2021/09/06 00:36:01 millert Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@@ -15,6 +15,7 @@
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#ifdef __OpenBSD__
#include <sys/sysctl.h>
#endif
@@ -78,8 +79,8 @@ static void add_listen_addr(ServerOptions *, const char *,
const char *, int);
static void add_one_listen_addr(ServerOptions *, const char *,
const char *, int);
-void parse_server_config_depth(ServerOptions *options, const char *filename,
- struct sshbuf *conf, struct include_list *includes,
+static void parse_server_config_depth(ServerOptions *options,
+ const char *filename, struct sshbuf *conf, struct include_list *includes,
struct connection_info *connectinfo, int flags, int *activep, int depth);
/* Use of privilege separation or not */
@@ -125,13 +126,15 @@ initialize_server_options(ServerOptions *options)
options->tcp_keep_alive = -1;
options->log_facility = SYSLOG_FACILITY_NOT_SET;
options->log_level = SYSLOG_LEVEL_NOT_SET;
+ options->num_log_verbose = 0;
+ options->log_verbose = NULL;
options->hostbased_authentication = -1;
options->hostbased_uses_name_from_packet_only = -1;
- options->hostbased_key_types = NULL;
+ options->hostbased_accepted_algos = NULL;
options->hostkeyalgorithms = NULL;
options->pubkey_authentication = -1;
options->pubkey_auth_options = -1;
- options->pubkey_key_types = NULL;
+ options->pubkey_accepted_algos = NULL;
options->kerberos_authentication = -1;
options->kerberos_or_local_passwd = -1;
options->kerberos_ticket_cleanup = -1;
@@ -141,10 +144,9 @@ initialize_server_options(ServerOptions *options)
options->gss_strict_acceptor = -1;
options->password_authentication = -1;
options->kbd_interactive_authentication = -1;
- options->challenge_response_authentication = -1;
options->permit_empty_passwd = -1;
options->permit_user_env = -1;
- options->permit_user_env_whitelist = NULL;
+ options->permit_user_env_allowlist = NULL;
options->compression = -1;
options->rekey_limit = -1;
options->rekey_interval = -1;
@@ -166,6 +168,9 @@ initialize_server_options(ServerOptions *options)
options->max_startups_begin = -1;
options->max_startups_rate = -1;
options->max_startups = -1;
+ options->per_source_max_startups = -1;
+ options->per_source_masklen_ipv4 = -1;
+ options->per_source_masklen_ipv6 = -1;
options->max_authtries = -1;
options->max_sessions = -1;
options->banner = NULL;
@@ -216,22 +221,22 @@ assemble_algorithms(ServerOptions *o)
all_key = sshkey_alg_list(0, 0, 1, ',');
all_sig = sshkey_alg_list(0, 1, 1, ',');
/* remove unsupported algos from default lists */
- def_cipher = match_filter_whitelist(KEX_SERVER_ENCRYPT, all_cipher);
- def_mac = match_filter_whitelist(KEX_SERVER_MAC, all_mac);
- def_kex = match_filter_whitelist(KEX_SERVER_KEX, all_kex);
- def_key = match_filter_whitelist(KEX_DEFAULT_PK_ALG, all_key);
- def_sig = match_filter_whitelist(SSH_ALLOWED_CA_SIGALGS, all_sig);
+ def_cipher = match_filter_allowlist(KEX_SERVER_ENCRYPT, all_cipher);
+ def_mac = match_filter_allowlist(KEX_SERVER_MAC, all_mac);
+ def_kex = match_filter_allowlist(KEX_SERVER_KEX, all_kex);
+ def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
+ def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
#define ASSEMBLE(what, defaults, all) \
do { \
if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \
- fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \
+ fatal_fr(r, "%s", #what); \
} while (0)
ASSEMBLE(ciphers, def_cipher, all_cipher);
ASSEMBLE(macs, def_mac, all_mac);
ASSEMBLE(kex_algorithms, def_kex, all_kex);
ASSEMBLE(hostkeyalgorithms, def_key, all_key);
- ASSEMBLE(hostbased_key_types, def_key, all_key);
- ASSEMBLE(pubkey_key_types, def_key, all_key);
+ ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
+ ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
#undef ASSEMBLE
free(all_cipher);
@@ -246,39 +251,13 @@ assemble_algorithms(ServerOptions *o)
free(def_sig);
}
-static void
-array_append2(const char *file, const int line, const char *directive,
- char ***array, int **iarray, u_int *lp, const char *s, int i)
-{
-
- if (*lp >= INT_MAX)
- fatal("%s line %d: Too many %s entries", file, line, directive);
-
- if (iarray != NULL) {
- *iarray = xrecallocarray(*iarray, *lp, *lp + 1,
- sizeof(**iarray));
- (*iarray)[*lp] = i;
- }
-
- *array = xrecallocarray(*array, *lp, *lp + 1, sizeof(**array));
- (*array)[*lp] = xstrdup(s);
- (*lp)++;
-}
-
-static void
-array_append(const char *file, const int line, const char *directive,
- char ***array, u_int *lp, const char *s)
-{
- array_append2(file, line, directive, array, NULL, lp, s, 0);
-}
-
void
servconf_add_hostkey(const char *file, const int line,
ServerOptions *options, const char *path, int userprovided)
{
char *apath = derelativise_path(path);
- array_append2(file, line, "HostKey",
+ opt_array_append2(file, line, "HostKey",
&options->host_key_files, &options->host_key_file_userprovided,
&options->num_host_key_files, apath, userprovided);
free(apath);
@@ -290,7 +269,7 @@ servconf_add_hostcert(const char *file, const int line,
{
char *apath = derelativise_path(path);
- array_append(file, line, "HostCertificate",
+ opt_array_append(file, line, "HostCertificate",
&options->host_cert_files, &options->num_host_cert_files, apath);
free(apath);
}
@@ -329,6 +308,8 @@ fill_default_server_options(ServerOptions *options)
add_listen_addr(options, NULL, NULL, 0);
if (options->pid_file == NULL)
options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE);
+ if (options->moduli_file == NULL)
+ options->moduli_file = xstrdup(_PATH_DH_MODULI);
if (options->login_grace_time == -1)
options->login_grace_time = 120;
if (options->permit_root_login == PERMIT_NOT_SET)
@@ -386,14 +367,12 @@ fill_default_server_options(ServerOptions *options)
if (options->password_authentication == -1)
options->password_authentication = 1;
if (options->kbd_interactive_authentication == -1)
- options->kbd_interactive_authentication = 0;
- if (options->challenge_response_authentication == -1)
- options->challenge_response_authentication = 1;
+ options->kbd_interactive_authentication = 1;
if (options->permit_empty_passwd == -1)
options->permit_empty_passwd = 0;
if (options->permit_user_env == -1) {
options->permit_user_env = 0;
- options->permit_user_env_whitelist = NULL;
+ options->permit_user_env_allowlist = NULL;
}
if (options->compression == -1)
#ifdef WITH_ZLIB
@@ -420,6 +399,12 @@ fill_default_server_options(ServerOptions *options)
options->max_startups_rate = 30; /* 30% */
if (options->max_startups_begin == -1)
options->max_startups_begin = 10;
+ if (options->per_source_max_startups == -1)
+ options->per_source_max_startups = INT_MAX;
+ if (options->per_source_masklen_ipv4 == -1)
+ options->per_source_masklen_ipv4 = 32;
+ if (options->per_source_masklen_ipv6 == -1)
+ options->per_source_masklen_ipv6 = 128;
if (options->max_authtries == -1)
options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
if (options->max_sessions == -1)
@@ -431,11 +416,11 @@ fill_default_server_options(ServerOptions *options)
if (options->client_alive_count_max == -1)
options->client_alive_count_max = 3;
if (options->num_authkeys_files == 0) {
- array_append("[default]", 0, "AuthorizedKeysFiles",
+ opt_array_append("[default]", 0, "AuthorizedKeysFiles",
&options->authorized_keys_files,
&options->num_authkeys_files,
_PATH_SSH_USER_PERMITTED_KEYS);
- array_append("[default]", 0, "AuthorizedKeysFiles",
+ opt_array_append("[default]", 0, "AuthorizedKeysFiles",
&options->authorized_keys_files,
&options->num_authkeys_files,
_PATH_SSH_USER_PERMITTED_KEYS2);
@@ -498,15 +483,6 @@ fill_default_server_options(ServerOptions *options)
options->auth_methods[0] = NULL;
options->num_auth_methods = 0;
}
-
-#ifndef HAVE_MMAP
- if (use_privsep && options->compression == 1) {
- error("This platform does not support both privilege "
- "separation and compression");
- error("Compression disabled");
- options->compression = 0;
- }
-#endif
}
/* Keyword tokens. */
@@ -516,23 +492,21 @@ typedef enum {
sUsePAM,
/* Standard Options */
sPort, sHostKeyFile, sLoginGraceTime,
- sPermitRootLogin, sLogFacility, sLogLevel,
- sRhostsRSAAuthentication, sRSAAuthentication,
+ sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose,
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
- sKerberosGetAFSToken, sChallengeResponseAuthentication,
- sPasswordAuthentication, sKbdInteractiveAuthentication,
- sListenAddress, sAddressFamily,
+ sKerberosGetAFSToken, sPasswordAuthentication,
+ sKbdInteractiveAuthentication, sListenAddress, sAddressFamily,
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive,
sPermitUserEnvironment, sAllowTcpForwarding, sCompression,
sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
- sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile,
- sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedKeyTypes,
+ sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile, sModuliFile,
+ sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedAlgorithms,
sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions,
sBanner, sUseDNS, sHostbasedAuthentication,
- sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes,
- sHostKeyAlgorithms,
+ sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedAlgorithms,
+ sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize,
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
sAcceptEnv, sSetEnv, sPermitTunnel,
@@ -554,6 +528,7 @@ typedef enum {
#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */
#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH)
#define SSHCFG_NEVERMATCH 0x04 /* Match never matches; internal only */
+#define SSHCFG_MATCH_ONLY 0x08 /* Match only in conditional blocks; internal only */
/* Textual representation of the tokens. */
static struct {
@@ -574,21 +549,25 @@ static struct {
{ "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */
{ "hostkeyagent", sHostKeyAgent, SSHCFG_GLOBAL },
{ "pidfile", sPidFile, SSHCFG_GLOBAL },
+ { "modulifile", sModuliFile, SSHCFG_GLOBAL },
{ "serverkeybits", sDeprecated, SSHCFG_GLOBAL },
{ "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
{ "keyregenerationinterval", sDeprecated, SSHCFG_GLOBAL },
{ "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
{ "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
{ "loglevel", sLogLevel, SSHCFG_ALL },
+ { "logverbose", sLogVerbose, SSHCFG_ALL },
{ "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
{ "rhostsrsaauthentication", sDeprecated, SSHCFG_ALL },
{ "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
{ "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_ALL },
- { "hostbasedacceptedkeytypes", sHostbasedAcceptedKeyTypes, SSHCFG_ALL },
+ { "hostbasedacceptedalgorithms", sHostbasedAcceptedAlgorithms, SSHCFG_ALL },
+ { "hostbasedacceptedkeytypes", sHostbasedAcceptedAlgorithms, SSHCFG_ALL }, /* obsolete */
{ "hostkeyalgorithms", sHostKeyAlgorithms, SSHCFG_GLOBAL },
{ "rsaauthentication", sDeprecated, SSHCFG_ALL },
{ "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
- { "pubkeyacceptedkeytypes", sPubkeyAcceptedKeyTypes, SSHCFG_ALL },
+ { "pubkeyacceptedalgorithms", sPubkeyAcceptedAlgorithms, SSHCFG_ALL },
+ { "pubkeyacceptedkeytypes", sPubkeyAcceptedAlgorithms, SSHCFG_ALL }, /* obsolete */
{ "pubkeyauthoptions", sPubkeyAuthOptions, SSHCFG_ALL },
{ "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
#ifdef KRB5
@@ -619,8 +598,8 @@ static struct {
#endif
{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
- { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
- { "skeyauthentication", sDeprecated, SSHCFG_GLOBAL },
+ { "challengeresponseauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */
+ { "skeyauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */
{ "checkmail", sDeprecated, SSHCFG_GLOBAL },
{ "listenaddress", sListenAddress, SSHCFG_GLOBAL },
{ "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
@@ -656,6 +635,8 @@ static struct {
{ "gatewayports", sGatewayPorts, SSHCFG_ALL },
{ "subsystem", sSubsystem, SSHCFG_GLOBAL },
{ "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
+ { "persourcemaxstartups", sPerSourceMaxStartups, SSHCFG_GLOBAL },
+ { "persourcenetblocksize", sPerSourceNetBlockSize, SSHCFG_GLOBAL },
{ "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
{ "maxsessions", sMaxSessions, SSHCFG_ALL },
{ "banner", sBanner, SSHCFG_ALL },
@@ -759,7 +740,7 @@ derelativise_path(const char *path)
if (path_absolute(expanded))
return expanded;
if (getcwd(cwd, sizeof(cwd)) == NULL)
- fatal("%s: getcwd: %s", __func__, strerror(errno));
+ fatal_f("getcwd: %s", strerror(errno));
xasprintf(&ret, "%s/%s", cwd, expanded);
free(expanded);
return ret;
@@ -802,7 +783,7 @@ add_one_listen_addr(ServerOptions *options, const char *addr,
if (i >= options->num_listen_addrs) {
/* No entry for this rdomain; allocate one */
if (i >= INT_MAX)
- fatal("%s: too many listen addresses", __func__);
+ fatal_f("too many listen addresses");
options->listen_addrs = xrecallocarray(options->listen_addrs,
options->num_listen_addrs, options->num_listen_addrs + 1,
sizeof(*options->listen_addrs));
@@ -939,10 +920,10 @@ process_permitopen_list(struct ssh *ssh, ServerOpCodes opcode,
ch = '\0';
host = hpdelim2(&arg, &ch);
if (host == NULL || ch == '/')
- fatal("%s: missing host in %s", __func__, what);
+ fatal_f("missing host in %s", what);
host = cleanhostname(host);
if (arg == NULL || ((port = permitopen_port(arg)) < 0))
- fatal("%s: bad port number in %s", __func__, what);
+ fatal_f("bad port number in %s", what);
/* Send it to channels layer */
channel_add_permission(ssh, FORWARD_ADM,
where, host, port);
@@ -1067,18 +1048,29 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
ci->laddress ? ci->laddress : "(null)", ci->lport);
while ((attrib = strdelim(&cp)) && *attrib != '\0') {
+ /* Terminate on comment */
+ if (*attrib == '#') {
+ cp = NULL; /* mark all arguments consumed */
+ break;
+ }
+ arg = NULL;
attributes++;
+ /* Criterion "all" has no argument and must appear alone */
if (strcasecmp(attrib, "all") == 0) {
- if (attributes != 1 ||
- ((arg = strdelim(&cp)) != NULL && *arg != '\0')) {
+ if (attributes > 1 || ((arg = strdelim(&cp)) != NULL &&
+ *arg != '\0' && *arg != '#')) {
error("'all' cannot be combined with other "
"Match attributes");
return -1;
}
+ if (arg != NULL && *arg == '#')
+ cp = NULL; /* mark all arguments consumed */
*condition = cp;
return 1;
}
- if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
+ /* All other criteria require an argument */
+ if ((arg = strdelim(&cp)) == NULL ||
+ *arg == '\0' || *arg == '#') {
error("Missing Match criteria for %s", attrib);
return -1;
}
@@ -1121,6 +1113,9 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
"%.100s' at line %d", ci->host, arg, line);
} else if (strcasecmp(attrib, "address") == 0) {
if (ci == NULL || (ci->test && ci->address == NULL)) {
+ if (addr_match_list(NULL, arg) != 0)
+ fatal("Invalid Match address argument "
+ "'%s' at line %d", arg, line);
result = 0;
continue;
}
@@ -1140,6 +1135,10 @@ match_cfg_line(char **condition, int line, struct connection_info *ci)
}
} else if (strcasecmp(attrib, "localaddress") == 0){
if (ci == NULL || (ci->test && ci->laddress == NULL)) {
+ if (addr_match_list(NULL, arg) != 0)
+ fatal("Invalid Match localaddress "
+ "argument '%s' at line %d", arg,
+ line);
result = 0;
continue;
}
@@ -1263,10 +1262,10 @@ static const struct multistate multistate_tcpfwd[] = {
static int
process_server_config_line_depth(ServerOptions *options, char *line,
const char *filename, int linenum, int *activep,
- struct connection_info *connectinfo, int inc_flags, int depth,
+ struct connection_info *connectinfo, int *inc_flags, int depth,
struct include_list *includes)
{
- char ch, *cp, ***chararrayptr, **charptr, *arg, *arg2, *p;
+ char ch, *str, ***chararrayptr, **charptr, *arg, *arg2, *p, *keyword;
int cmdline = 0, *intptr, value, value2, n, port, oactive, r, found;
SyslogFacility *log_facility_ptr;
LogLevel *log_level_ptr;
@@ -1278,6 +1277,9 @@ process_server_config_line_depth(ServerOptions *options, char *line,
const char *errstr;
struct include_item *item;
glob_t gbuf;
+ char **oav = NULL, **av;
+ int oac = 0, ac;
+ int ret = -1;
/* Strip trailing whitespace. Allow \f (form feed) at EOL only */
if ((len = strlen(line)) == 0)
@@ -1288,32 +1290,43 @@ process_server_config_line_depth(ServerOptions *options, char *line,
line[len] = '\0';
}
- cp = line;
- if ((arg = strdelim(&cp)) == NULL)
+ str = line;
+ if ((keyword = strdelim(&str)) == NULL)
return 0;
/* Ignore leading whitespace */
- if (*arg == '\0')
- arg = strdelim(&cp);
- if (!arg || !*arg || *arg == '#')
+ if (*keyword == '\0')
+ keyword = strdelim(&str);
+ if (!keyword || !*keyword || *keyword == '#')
return 0;
+ if (str == NULL || *str == '\0') {
+ error("%s line %d: no argument after keyword \"%s\"",
+ filename, linenum, keyword);
+ return -1;
+ }
intptr = NULL;
charptr = NULL;
- opcode = parse_token(arg, filename, linenum, &flags);
+ opcode = parse_token(keyword, filename, linenum, &flags);
+
+ if (argv_split(str, &oac, &oav, 1) != 0) {
+ error("%s line %d: invalid quotes", filename, linenum);
+ return -1;
+ }
+ ac = oac;
+ av = oav;
if (activep == NULL) { /* We are processing a command line directive */
cmdline = 1;
activep = &cmdline;
}
if (*activep && opcode != sMatch && opcode != sInclude)
- debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
+ debug3("%s:%d setting %s %s", filename, linenum, keyword, str);
if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
if (connectinfo == NULL) {
fatal("%s line %d: Directive '%s' is not allowed "
- "within a Match block", filename, linenum, arg);
+ "within a Match block", filename, linenum, keyword);
} else { /* this is a directive we have already processed */
- while (arg)
- arg = strdelim(&cp);
- return 0;
+ ret = 0;
+ goto out;
}
}
@@ -1325,15 +1338,17 @@ process_server_config_line_depth(ServerOptions *options, char *line,
/* Standard Options */
case sBadOption:
- return -1;
+ goto out;
case sPort:
/* ignore ports from configfile if cmdline specifies ports */
- if (options->ports_from_cmdline)
- return 0;
+ if (options->ports_from_cmdline) {
+ argv_consume(&ac);
+ break;
+ }
if (options->num_ports >= MAX_PORTS)
fatal("%s line %d: too many ports.",
filename, linenum);
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
fatal("%s line %d: missing port number.",
filename, linenum);
@@ -1346,7 +1361,7 @@ process_server_config_line_depth(ServerOptions *options, char *line,
case sLoginGraceTime:
intptr = &options->login_grace_time;
parse_time:
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
fatal("%s line %d: missing time value.",
filename, linenum);
@@ -1358,7 +1373,7 @@ process_server_config_line_depth(ServerOptions *options, char *line,
break;
case sListenAddress:
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (arg == NULL || *arg == '\0')
fatal("%s line %d: missing address",
filename, linenum);
@@ -1383,16 +1398,15 @@ process_server_config_line_depth(ServerOptions *options, char *line,
}
/* Optional routing table */
arg2 = NULL;
- if ((arg = strdelim(&cp)) != NULL) {
+ if ((arg = argv_next(&ac, &av)) != NULL) {
if (strcmp(arg, "rdomain") != 0 ||
- (arg2 = strdelim(&cp)) == NULL)
+ (arg2 = argv_next(&ac, &av)) == NULL)
fatal("%s line %d: bad ListenAddress syntax",
filename, linenum);
if (!valid_rdomain(arg2))
fatal("%s line %d: bad routing domain",
filename, linenum);
}
-
queue_listen_addr(options, p, arg2, port);
break;
@@ -1401,7 +1415,7 @@ process_server_config_line_depth(ServerOptions *options, char *line,
intptr = &options->address_family;
multistate_ptr = multistate_addressfamily;
parse_multistate:
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
fatal("%s line %d: missing argument.",
filename, linenum);
@@ -1420,7 +1434,7 @@ process_server_config_line_depth(ServerOptions *options, char *line,
break;
case sHostKeyFile:
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
filename, linenum);
@@ -1432,7 +1446,7 @@ process_server_config_line_depth(ServerOptions *options, char *line,
case sHostKeyAgent:
charptr = &options->host_key_agent;
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
fatal("%s line %d: missing socket name.",
filename, linenum);
@@ -1442,7 +1456,7 @@ process_server_config_line_depth(ServerOptions *options, char *line,
break;
case sHostCertificate:
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
filename, linenum);
@@ -1453,7 +1467,7 @@ process_server_config_line_depth(ServerOptions *options, char *line,
case sPidFile:
charptr = &options->pid_file;
parse_filename:
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
fatal("%s line %d: missing file name.",
filename, linenum);
@@ -1465,6 +1479,10 @@ process_server_config_line_depth(ServerOptions *options, char *line,
}
break;
+ case sModuliFile:
+ charptr = &options->moduli_file;
+ goto parse_filename;
+
case sPermitRootLogin:
intptr = &options->permit_root_login;
multistate_ptr = multistate_permitrootlogin;
@@ -1489,10 +1507,10 @@ process_server_config_line_depth(ServerOptions *options, char *line,
intptr = &options->hostbased_uses_name_from_packet_only;
goto parse_flag;
- case sHostbasedAcceptedKeyTypes:
- charptr = &options->hostbased_key_types;
- parse_keytypes:
- arg = strdelim(&cp);
+ case sHostbasedAcceptedAlgorithms:
+ charptr = &options->hostbased_accepted_algos;
+ parse_pubkey_algos:
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing argument.",
filename, linenum);
@@ -1507,32 +1525,34 @@ process_server_config_line_depth(ServerOptions *options, char *line,
case sHostKeyAlgorithms:
charptr = &options->hostkeyalgorithms;
- goto parse_keytypes;
+ goto parse_pubkey_algos;
case sCASignatureAlgorithms:
charptr = &options->ca_sign_algorithms;
- goto parse_keytypes;
+ goto parse_pubkey_algos;
case sPubkeyAuthentication:
intptr = &options->pubkey_authentication;
goto parse_flag;
- case sPubkeyAcceptedKeyTypes:
- charptr = &options->pubkey_key_types;
- goto parse_keytypes;
+ case sPubkeyAcceptedAlgorithms:
+ charptr = &options->pubkey_accepted_algos;
+ goto parse_pubkey_algos;
case sPubkeyAuthOptions:
intptr = &options->pubkey_auth_options;
value = 0;
- while ((arg = strdelim(&cp)) && *arg != '\0') {
+ while ((arg = argv_next(&ac, &av)) != NULL) {
if (strcasecmp(arg, "none") == 0)
continue;
if (strcasecmp(arg, "touch-required") == 0)
value |= PUBKEYAUTH_TOUCH_REQUIRED;
+ else if (strcasecmp(arg, "verify-required") == 0)
+ value |= PUBKEYAUTH_VERIFY_REQUIRED;
else {
- fatal("%s line %d: unsupported "
- "PubkeyAuthOptions option %s",
- filename, linenum, arg);
+ error("%s line %d: unsupported %s option %s",
+ filename, linenum, keyword, arg);
+ goto out;
}
}
if (*activep && *intptr == -1)
@@ -1575,10 +1595,6 @@ process_server_config_line_depth(ServerOptions *options, char *line,
intptr = &options->kbd_interactive_authentication;
goto parse_flag;
- case sChallengeResponseAuthentication:
- intptr = &options->challenge_response_authentication;
- goto parse_flag;
-
case sPrintMotd:
intptr = &options->print_motd;
goto parse_flag;
@@ -1594,10 +1610,10 @@ process_server_config_line_depth(ServerOptions *options, char *line,
case sX11DisplayOffset:
intptr = &options->x11_display_offset;
parse_int:
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if ((errstr = atoi_err(arg, &value)) != NULL)
- fatal("%s line %d: integer value %s.",
- filename, linenum, errstr);
+ fatal("%s line %d: %s integer value %s.",
+ filename, linenum, keyword, errstr);
if (*activep && *intptr == -1)
*intptr = value;
break;
@@ -1632,11 +1648,11 @@ process_server_config_line_depth(ServerOptions *options, char *line,
case sPermitUserEnvironment:
intptr = &options->permit_user_env;
- charptr = &options->permit_user_env_whitelist;
- arg = strdelim(&cp);
+ charptr = &options->permit_user_env_allowlist;
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
- fatal("%s line %d: missing argument.",
- filename, linenum);
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
value = 0;
p = NULL;
if (strcmp(arg, "yes") == 0)
@@ -1662,25 +1678,26 @@ process_server_config_line_depth(ServerOptions *options, char *line,
goto parse_multistate;
case sRekeyLimit:
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.", filename,
- linenum);
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
if (strcmp(arg, "default") == 0) {
val64 = 0;
} else {
if (scan_scaled(arg, &val64) == -1)
- fatal("%.200s line %d: Bad number '%s': %s",
- filename, linenum, arg, strerror(errno));
+ fatal("%.200s line %d: Bad %s number '%s': %s",
+ filename, linenum, keyword,
+ arg, strerror(errno));
if (val64 != 0 && val64 < 16)
- fatal("%.200s line %d: RekeyLimit too small",
- filename, linenum);
+ fatal("%.200s line %d: %s too small",
+ filename, linenum, keyword);
}
if (*activep && options->rekey_limit == -1)
options->rekey_limit = val64;
- if (cp != NULL) { /* optional rekey interval present */
- if (strcmp(cp, "none") == 0) {
- (void)strdelim(&cp); /* discard */
+ if (ac != 0) { /* optional rekey interval present */
+ if (strcmp(av[0], "none") == 0) {
+ (void)argv_next(&ac, &av); /* discard */
break;
}
intptr = &options->rekey_interval;
@@ -1699,7 +1716,7 @@ process_server_config_line_depth(ServerOptions *options, char *line,
case sLogFacility:
log_facility_ptr = &options->log_facility;
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
value = log_facility_number(arg);
if (value == SYSLOG_FACILITY_NOT_SET)
fatal("%.200s line %d: unsupported log facility '%s'",
@@ -1710,7 +1727,7 @@ process_server_config_line_depth(ServerOptions *options, char *line,
case sLogLevel:
log_level_ptr = &options->log_level;
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
value = log_level_number(arg);
if (value == SYSLOG_LEVEL_NOT_SET)
fatal("%.200s line %d: unsupported log level '%s'",
@@ -1719,6 +1736,33 @@ process_server_config_line_depth(ServerOptions *options, char *line,
*log_level_ptr = (LogLevel) value;
break;
+ case sLogVerbose:
+ found = options->num_log_verbose == 0;
+ i = 0;
+ while ((arg = argv_next(&ac, &av)) != NULL) {
+ if (*arg == '\0') {
+ error("%s line %d: keyword %s empty argument",
+ filename, linenum, keyword);
+ goto out;
+ }
+ /* Allow "none" only in first position */
+ if (strcasecmp(arg, "none") == 0) {
+ if (i > 0 || ac > 0) {
+ error("%s line %d: keyword %s \"none\" "
+ "argument must appear alone.",
+ filename, linenum, keyword);
+ goto out;
+ }
+ }
+ i++;
+ if (!found || !*activep)
+ continue;
+ opt_array_append(filename, linenum, keyword,
+ &options->log_verbose, &options->num_log_verbose,
+ arg);
+ }
+ break;
+
case sAllowTcpForwarding:
intptr = &options->allow_tcp_forwarding;
multistate_ptr = multistate_tcpfwd;
@@ -1738,55 +1782,51 @@ process_server_config_line_depth(ServerOptions *options, char *line,
goto parse_flag;
case sAllowUsers:
- while ((arg = strdelim(&cp)) && *arg != '\0') {
- if (match_user(NULL, NULL, NULL, arg) == -1)
- fatal("%s line %d: invalid AllowUsers pattern: "
- "\"%.100s\"", filename, linenum, arg);
+ chararrayptr = &options->allow_users;
+ uintptr = &options->num_allow_users;
+ parse_allowdenyusers:
+ while ((arg = argv_next(&ac, &av)) != NULL) {
+ if (*arg == '\0' ||
+ match_user(NULL, NULL, NULL, arg) == -1)
+ fatal("%s line %d: invalid %s pattern: \"%s\"",
+ filename, linenum, keyword, arg);
if (!*activep)
continue;
- array_append(filename, linenum, "AllowUsers",
- &options->allow_users, &options->num_allow_users,
- arg);
+ opt_array_append(filename, linenum, keyword,
+ chararrayptr, uintptr, arg);
}
break;
case sDenyUsers:
- while ((arg = strdelim(&cp)) && *arg != '\0') {
- if (match_user(NULL, NULL, NULL, arg) == -1)
- fatal("%s line %d: invalid DenyUsers pattern: "
- "\"%.100s\"", filename, linenum, arg);
- if (!*activep)
- continue;
- array_append(filename, linenum, "DenyUsers",
- &options->deny_users, &options->num_deny_users,
- arg);
- }
- break;
+ chararrayptr = &options->deny_users;
+ uintptr = &options->num_deny_users;
+ goto parse_allowdenyusers;
case sAllowGroups:
- while ((arg = strdelim(&cp)) && *arg != '\0') {
+ chararrayptr = &options->allow_groups;
+ uintptr = &options->num_allow_groups;
+ parse_allowdenygroups:
+ while ((arg = argv_next(&ac, &av)) != NULL) {
+ if (*arg == '\0')
+ fatal("%s line %d: empty %s pattern",
+ filename, linenum, keyword);
if (!*activep)
continue;
- array_append(filename, linenum, "AllowGroups",
- &options->allow_groups, &options->num_allow_groups,
- arg);
+ opt_array_append(filename, linenum, keyword,
+ chararrayptr, uintptr, arg);
}
break;
case sDenyGroups:
- while ((arg = strdelim(&cp)) && *arg != '\0') {
- if (!*activep)
- continue;
- array_append(filename, linenum, "DenyGroups",
- &options->deny_groups, &options->num_deny_groups,
- arg);
- }
- break;
+ chararrayptr = &options->deny_groups;
+ uintptr = &options->num_deny_groups;
+ goto parse_allowdenygroups;
case sCiphers:
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
- fatal("%s line %d: Missing argument.", filename, linenum);
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
if (*arg != '-' &&
!ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg))
fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
@@ -1796,9 +1836,10 @@ process_server_config_line_depth(ServerOptions *options, char *line,
break;
case sMacs:
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
- fatal("%s line %d: Missing argument.", filename, linenum);
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
if (*arg != '-' &&
!mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg))
fatal("%s line %d: Bad SSH2 mac spec '%s'.",
@@ -1808,10 +1849,10 @@ process_server_config_line_depth(ServerOptions *options, char *line,
break;
case sKexAlgorithms:
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
- fatal("%s line %d: Missing argument.",
- filename, linenum);
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
if (*arg != '-' &&
!kex_names_valid(*arg == '+' || *arg == '^' ?
arg + 1 : arg))
@@ -1826,20 +1867,20 @@ process_server_config_line_depth(ServerOptions *options, char *line,
fatal("%s line %d: too many subsystems defined.",
filename, linenum);
}
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
- fatal("%s line %d: Missing subsystem name.",
- filename, linenum);
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
if (!*activep) {
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
break;
}
for (i = 0; i < options->num_subsystems; i++)
if (strcmp(arg, options->subsystem_name[i]) == 0)
- fatal("%s line %d: Subsystem '%s' already defined.",
- filename, linenum, arg);
+ fatal("%s line %d: Subsystem '%s' "
+ "already defined.", filename, linenum, arg);
options->subsystem_name[options->num_subsystems] = xstrdup(arg);
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
fatal("%s line %d: Missing subsystem command.",
filename, linenum);
@@ -1848,7 +1889,7 @@ process_server_config_line_depth(ServerOptions *options, char *line,
/* Collect arguments (separate to executable) */
p = xstrdup(arg);
len = strlen(p) + 1;
- while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
+ while ((arg = argv_next(&ac, &av)) != NULL) {
len += 1 + strlen(arg);
p = xreallocarray(p, 1, len);
strlcat(p, " ", len);
@@ -1859,10 +1900,10 @@ process_server_config_line_depth(ServerOptions *options, char *line,
break;
case sMaxStartups:
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
- fatal("%s line %d: Missing MaxStartups spec.",
- filename, linenum);
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
if ((n = sscanf(arg, "%d:%d:%d",
&options->max_startups_begin,
&options->max_startups_rate,
@@ -1871,15 +1912,54 @@ process_server_config_line_depth(ServerOptions *options, char *line,
options->max_startups ||
options->max_startups_rate > 100 ||
options->max_startups_rate < 1)
- fatal("%s line %d: Illegal MaxStartups spec.",
- filename, linenum);
+ fatal("%s line %d: Invalid %s spec.",
+ filename, linenum, keyword);
} else if (n != 1)
- fatal("%s line %d: Illegal MaxStartups spec.",
- filename, linenum);
+ fatal("%s line %d: Invalid %s spec.",
+ filename, linenum, keyword);
else
options->max_startups = options->max_startups_begin;
break;
+ case sPerSourceNetBlockSize:
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
+ switch (n = sscanf(arg, "%d:%d", &value, &value2)) {
+ case 2:
+ if (value2 < 0 || value2 > 128)
+ n = -1;
+ /* FALLTHROUGH */
+ case 1:
+ if (value < 0 || value > 32)
+ n = -1;
+ }
+ if (n != 1 && n != 2)
+ fatal("%s line %d: Invalid %s spec.",
+ filename, linenum, keyword);
+ if (*activep) {
+ options->per_source_masklen_ipv4 = value;
+ options->per_source_masklen_ipv6 = value2;
+ }
+ break;
+
+ case sPerSourceMaxStartups:
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
+ if (strcmp(arg, "none") == 0) { /* no limit */
+ value = INT_MAX;
+ } else {
+ if ((errstr = atoi_err(arg, &value)) != NULL)
+ fatal("%s line %d: %s integer value %s.",
+ filename, linenum, keyword, errstr);
+ }
+ if (*activep)
+ options->per_source_max_startups = value;
+ break;
+
case sMaxAuthTries:
intptr = &options->max_authtries;
goto parse_int;
@@ -1899,24 +1979,29 @@ process_server_config_line_depth(ServerOptions *options, char *line,
* AuthorizedKeysFile /etc/ssh_keys/%u
*/
case sAuthorizedKeysFile:
- if (*activep && options->num_authkeys_files == 0) {
- while ((arg = strdelim(&cp)) && *arg != '\0') {
- arg = tilde_expand_filename(arg, getuid());
- array_append(filename, linenum,
- "AuthorizedKeysFile",
+ uvalue = options->num_authkeys_files;
+ while ((arg = argv_next(&ac, &av)) != NULL) {
+ if (*arg == '\0') {
+ error("%s line %d: keyword %s empty argument",
+ filename, linenum, keyword);
+ goto out;
+ }
+ arg2 = tilde_expand_filename(arg, getuid());
+ if (*activep && uvalue == 0) {
+ opt_array_append(filename, linenum, keyword,
&options->authorized_keys_files,
- &options->num_authkeys_files, arg);
- free(arg);
+ &options->num_authkeys_files, arg2);
}
+ free(arg2);
}
- return 0;
+ break;
case sAuthorizedPrincipalsFile:
charptr = &options->authorized_principals_file;
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
- fatal("%s line %d: missing file name.",
- filename, linenum);
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
if (*activep && *charptr == NULL) {
*charptr = tilde_expand_filename(arg, getuid());
/* increase optional counter */
@@ -1934,13 +2019,13 @@ process_server_config_line_depth(ServerOptions *options, char *line,
goto parse_int;
case sAcceptEnv:
- while ((arg = strdelim(&cp)) && *arg != '\0') {
- if (strchr(arg, '=') != NULL)
+ while ((arg = argv_next(&ac, &av)) != NULL) {
+ if (*arg == '\0' || strchr(arg, '=') != NULL)
fatal("%s line %d: Invalid environment name.",
filename, linenum);
if (!*activep)
continue;
- array_append(filename, linenum, "AcceptEnv",
+ opt_array_append(filename, linenum, keyword,
&options->accept_env, &options->num_accept_env,
arg);
}
@@ -1948,23 +2033,23 @@ process_server_config_line_depth(ServerOptions *options, char *line,
case sSetEnv:
uvalue = options->num_setenv;
- while ((arg = strdelimw(&cp)) && *arg != '\0') {
- if (strchr(arg, '=') == NULL)
+ while ((arg = argv_next(&ac, &av)) != NULL) {
+ if (*arg == '\0' || strchr(arg, '=') == NULL)
fatal("%s line %d: Invalid environment.",
filename, linenum);
if (!*activep || uvalue != 0)
continue;
- array_append(filename, linenum, "SetEnv",
+ opt_array_append(filename, linenum, keyword,
&options->setenv, &options->num_setenv, arg);
}
break;
case sPermitTunnel:
intptr = &options->permit_tun;
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
- fatal("%s line %d: Missing yes/point-to-point/"
- "ethernet/no argument.", filename, linenum);
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
value = -1;
for (i = 0; tunmode_desc[i].val != -1; i++)
if (strcmp(tunmode_desc[i].text, arg) == 0) {
@@ -1972,8 +2057,8 @@ process_server_config_line_depth(ServerOptions *options, char *line,
break;
}
if (value == -1)
- fatal("%s line %d: Bad yes/point-to-point/ethernet/"
- "no argument: %s", filename, linenum, arg);
+ fatal("%s line %d: bad %s argument %s",
+ filename, linenum, keyword, arg);
if (*activep && *intptr == -1)
*intptr = value;
break;
@@ -1984,7 +2069,12 @@ process_server_config_line_depth(ServerOptions *options, char *line,
"command-line option");
}
value = 0;
- while ((arg2 = strdelim(&cp)) != NULL && *arg2 != '\0') {
+ while ((arg2 = argv_next(&ac, &av)) != NULL) {
+ if (*arg2 == '\0') {
+ error("%s line %d: keyword %s empty argument",
+ filename, linenum, keyword);
+ goto out;
+ }
value++;
found = 0;
if (*arg2 != '/' && *arg2 != '~') {
@@ -2006,7 +2096,9 @@ process_server_config_line_depth(ServerOptions *options, char *line,
parse_server_config_depth(options,
item->filename, item->contents,
includes, connectinfo,
- (oactive ? 0 : SSHCFG_NEVERMATCH),
+ (*inc_flags & SSHCFG_MATCH_ONLY
+ ? SSHCFG_MATCH_ONLY : (oactive
+ ? 0 : SSHCFG_NEVERMATCH)),
activep, depth + 1);
}
found = 1;
@@ -2022,9 +2114,8 @@ process_server_config_line_depth(ServerOptions *options, char *line,
filename, linenum, arg);
if ((r = glob(arg, 0, NULL, &gbuf)) != 0) {
if (r != GLOB_NOMATCH) {
- fatal("%s line %d: include \"%s\" "
- "glob failed", filename,
- linenum, arg);
+ fatal("%s line %d: include \"%s\" glob "
+ "failed", filename, linenum, arg);
}
/*
* If no entry matched then record a
@@ -2038,23 +2129,23 @@ process_server_config_line_depth(ServerOptions *options, char *line,
item, entry);
}
if (gbuf.gl_pathc > INT_MAX)
- fatal("%s: too many glob results", __func__);
+ fatal_f("too many glob results");
for (n = 0; n < (int)gbuf.gl_pathc; n++) {
debug2("%s line %d: including %s",
filename, linenum, gbuf.gl_pathv[n]);
item = xcalloc(1, sizeof(*item));
item->selector = strdup(arg);
item->filename = strdup(gbuf.gl_pathv[n]);
- if ((item->contents = sshbuf_new()) == NULL) {
- fatal("%s: sshbuf_new failed",
- __func__);
- }
+ if ((item->contents = sshbuf_new()) == NULL)
+ fatal_f("sshbuf_new failed");
load_server_config(item->filename,
item->contents);
parse_server_config_depth(options,
item->filename, item->contents,
includes, connectinfo,
- (oactive ? 0 : SSHCFG_NEVERMATCH),
+ (*inc_flags & SSHCFG_MATCH_ONLY
+ ? SSHCFG_MATCH_ONLY : (oactive
+ ? 0 : SSHCFG_NEVERMATCH)),
activep, depth + 1);
*activep = oactive;
TAILQ_INSERT_TAIL(includes, item, entry);
@@ -2063,20 +2154,32 @@ process_server_config_line_depth(ServerOptions *options, char *line,
free(arg);
}
if (value == 0) {
- fatal("%s line %d: Include missing filename argument",
- filename, linenum);
+ fatal("%s line %d: %s missing filename argument",
+ filename, linenum, keyword);
}
break;
case sMatch:
if (cmdline)
fatal("Match directive not supported as a command-line "
- "option");
- value = match_cfg_line(&cp, linenum, connectinfo);
+ "option");
+ value = match_cfg_line(&str, linenum,
+ (*inc_flags & SSHCFG_NEVERMATCH ? NULL : connectinfo));
if (value < 0)
fatal("%s line %d: Bad Match condition", filename,
linenum);
- *activep = (inc_flags & SSHCFG_NEVERMATCH) ? 0 : value;
+ *activep = (*inc_flags & SSHCFG_NEVERMATCH) ? 0 : value;
+ /*
+ * The MATCH_ONLY flag is applicable only until the first
+ * match block.
+ */
+ *inc_flags &= ~SSHCFG_MATCH_ONLY;
+ /*
+ * If match_cfg_line() didn't consume all its arguments then
+ * arrange for the extra arguments check below to fail.
+ */
+ if (str == NULL || *str == '\0')
+ argv_consume(&ac);
break;
case sPermitListen:
@@ -2088,10 +2191,10 @@ process_server_config_line_depth(ServerOptions *options, char *line,
uintptr = &options->num_permitted_opens;
chararrayptr = &options->permitted_opens;
}
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
- fatal("%s line %d: missing %s specification",
- filename, linenum, lookup_opcode_name(opcode));
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
uvalue = *uintptr; /* modified later */
if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) {
if (*activep && uvalue == 0) {
@@ -2102,7 +2205,7 @@ process_server_config_line_depth(ServerOptions *options, char *line,
}
break;
}
- for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
+ for (; arg != NULL && *arg != '\0'; arg = argv_next(&ac, &av)) {
if (opcode == sPermitListen &&
strchr(arg, ':') == NULL) {
/*
@@ -2115,21 +2218,18 @@ process_server_config_line_depth(ServerOptions *options, char *line,
ch = '\0';
p = hpdelim2(&arg, &ch);
if (p == NULL || ch == '/') {
- fatal("%s line %d: missing host in %s",
- filename, linenum,
- lookup_opcode_name(opcode));
+ fatal("%s line %d: %s missing host",
+ filename, linenum, keyword);
}
p = cleanhostname(p);
}
if (arg == NULL ||
((port = permitopen_port(arg)) < 0)) {
- fatal("%s line %d: bad port number in %s",
- filename, linenum,
- lookup_opcode_name(opcode));
+ fatal("%s line %d: %s bad port number",
+ filename, linenum, keyword);
}
if (*activep && uvalue == 0) {
- array_append(filename, linenum,
- lookup_opcode_name(opcode),
+ opt_array_append(filename, linenum, keyword,
chararrayptr, uintptr, arg2);
}
free(arg2);
@@ -2137,21 +2237,22 @@ process_server_config_line_depth(ServerOptions *options, char *line,
break;
case sForceCommand:
- if (cp == NULL || *cp == '\0')
- fatal("%.200s line %d: Missing argument.", filename,
- linenum);
- len = strspn(cp, WHITESPACE);
+ if (str == NULL || *str == '\0')
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
+ len = strspn(str, WHITESPACE);
if (*activep && options->adm_forced_command == NULL)
- options->adm_forced_command = xstrdup(cp + len);
- return 0;
+ options->adm_forced_command = xstrdup(str + len);
+ argv_consume(&ac);
+ break;
case sChrootDirectory:
charptr = &options->chroot_directory;
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
- fatal("%s line %d: missing file name.",
- filename, linenum);
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
@@ -2166,10 +2267,10 @@ process_server_config_line_depth(ServerOptions *options, char *line,
case sSecurityKeyProvider:
charptr = &options->sk_provider;
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
- fatal("%s line %d: missing file name.",
- filename, linenum);
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
if (*activep && *charptr == NULL) {
*charptr = strcasecmp(arg, "internal") == 0 ?
xstrdup(arg) : derelativise_path(arg);
@@ -2180,16 +2281,19 @@ process_server_config_line_depth(ServerOptions *options, char *line,
break;
case sIPQoS:
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
if ((value = parse_ipqos(arg)) == -1)
- fatal("%s line %d: Bad IPQoS value: %s",
- filename, linenum, arg);
- arg = strdelim(&cp);
+ fatal("%s line %d: Bad %s value: %s",
+ filename, linenum, keyword, arg);
+ arg = argv_next(&ac, &av);
if (arg == NULL)
value2 = value;
else if ((value2 = parse_ipqos(arg)) == -1)
- fatal("%s line %d: Bad IPQoS value: %s",
- filename, linenum, arg);
+ fatal("%s line %d: Bad %s value: %s",
+ filename, linenum, keyword, arg);
if (*activep) {
options->ip_qos_interactive = value;
options->ip_qos_bulk = value2;
@@ -2197,120 +2301,102 @@ process_server_config_line_depth(ServerOptions *options, char *line,
break;
case sVersionAddendum:
- if (cp == NULL || *cp == '\0')
- fatal("%.200s line %d: Missing argument.", filename,
- linenum);
- len = strspn(cp, WHITESPACE);
+ if (str == NULL || *str == '\0')
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
+ len = strspn(str, WHITESPACE);
+ if (strchr(str + len, '\r') != NULL) {
+ fatal("%.200s line %d: Invalid %s argument",
+ filename, linenum, keyword);
+ }
+ if ((arg = strchr(line, '#')) != NULL) {
+ *arg = '\0';
+ rtrim(line);
+ }
if (*activep && options->version_addendum == NULL) {
- if (strcasecmp(cp + len, "none") == 0)
+ if (strcasecmp(str + len, "none") == 0)
options->version_addendum = xstrdup("");
- else if (strchr(cp + len, '\r') != NULL)
- fatal("%.200s line %d: Invalid argument",
- filename, linenum);
else
- options->version_addendum = xstrdup(cp + len);
+ options->version_addendum = xstrdup(str + len);
}
- return 0;
+ argv_consume(&ac);
+ break;
case sAuthorizedKeysCommand:
- if (cp == NULL)
- fatal("%.200s line %d: Missing argument.", filename,
- linenum);
- len = strspn(cp, WHITESPACE);
- if (*activep && options->authorized_keys_command == NULL) {
- if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0)
- fatal("%.200s line %d: AuthorizedKeysCommand "
- "must be an absolute path",
- filename, linenum);
- options->authorized_keys_command = xstrdup(cp + len);
+ charptr = &options->authorized_keys_command;
+ parse_command:
+ len = strspn(str, WHITESPACE);
+ if (str[len] != '/' && strcasecmp(str + len, "none") != 0) {
+ fatal("%.200s line %d: %s must be an absolute path",
+ filename, linenum, keyword);
}
- return 0;
+ if (*activep && options->authorized_keys_command == NULL)
+ *charptr = xstrdup(str + len);
+ argv_consume(&ac);
+ break;
case sAuthorizedKeysCommandUser:
charptr = &options->authorized_keys_command_user;
-
- arg = strdelim(&cp);
- if (!arg || *arg == '\0')
- fatal("%s line %d: missing AuthorizedKeysCommandUser "
- "argument.", filename, linenum);
+ parse_localuser:
+ arg = argv_next(&ac, &av);
+ if (!arg || *arg == '\0') {
+ fatal("%s line %d: missing %s argument.",
+ filename, linenum, keyword);
+ }
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
break;
case sAuthorizedPrincipalsCommand:
- if (cp == NULL)
- fatal("%.200s line %d: Missing argument.", filename,
- linenum);
- len = strspn(cp, WHITESPACE);
- if (*activep &&
- options->authorized_principals_command == NULL) {
- if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0)
- fatal("%.200s line %d: "
- "AuthorizedPrincipalsCommand must be "
- "an absolute path", filename, linenum);
- options->authorized_principals_command =
- xstrdup(cp + len);
- }
- return 0;
+ charptr = &options->authorized_principals_command;
+ goto parse_command;
case sAuthorizedPrincipalsCommandUser:
charptr = &options->authorized_principals_command_user;
-
- arg = strdelim(&cp);
- if (!arg || *arg == '\0')
- fatal("%s line %d: missing "
- "AuthorizedPrincipalsCommandUser argument.",
- filename, linenum);
- if (*activep && *charptr == NULL)
- *charptr = xstrdup(arg);
- break;
+ goto parse_localuser;
case sAuthenticationMethods:
- if (options->num_auth_methods == 0) {
- value = 0; /* seen "any" pseudo-method */
- value2 = 0; /* successfully parsed any method */
- while ((arg = strdelim(&cp)) && *arg != '\0') {
- if (strcmp(arg, "any") == 0) {
- if (options->num_auth_methods > 0) {
- fatal("%s line %d: \"any\" "
- "must appear alone in "
- "AuthenticationMethods",
- filename, linenum);
- }
- value = 1;
- } else if (value) {
- fatal("%s line %d: \"any\" must appear "
- "alone in AuthenticationMethods",
- filename, linenum);
- } else if (auth2_methods_valid(arg, 0) != 0) {
- fatal("%s line %d: invalid "
- "authentication method list.",
- filename, linenum);
+ found = options->num_auth_methods == 0;
+ value = 0; /* seen "any" pseudo-method */
+ value2 = 0; /* successfully parsed any method */
+ while ((arg = argv_next(&ac, &av)) != NULL) {
+ if (strcmp(arg, "any") == 0) {
+ if (options->num_auth_methods > 0) {
+ fatal("%s line %d: \"any\" must "
+ "appear alone in %s",
+ filename, linenum, keyword);
}
- value2 = 1;
- if (!*activep)
- continue;
- array_append(filename, linenum,
- "AuthenticationMethods",
- &options->auth_methods,
- &options->num_auth_methods, arg);
- }
- if (value2 == 0) {
- fatal("%s line %d: no AuthenticationMethods "
- "specified", filename, linenum);
+ value = 1;
+ } else if (value) {
+ fatal("%s line %d: \"any\" must appear "
+ "alone in %s", filename, linenum, keyword);
+ } else if (auth2_methods_valid(arg, 0) != 0) {
+ fatal("%s line %d: invalid %s method list.",
+ filename, linenum, keyword);
}
+ value2 = 1;
+ if (!found || !*activep)
+ continue;
+ opt_array_append(filename, linenum, keyword,
+ &options->auth_methods,
+ &options->num_auth_methods, arg);
}
- return 0;
+ if (value2 == 0) {
+ fatal("%s line %d: no %s specified",
+ filename, linenum, keyword);
+ }
+ break;
case sStreamLocalBindMask:
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
- fatal("%s line %d: missing StreamLocalBindMask "
- "argument.", filename, linenum);
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
/* Parse mode in octal format */
value = strtol(arg, &p, 8);
if (arg == p || value < 0 || value > 0777)
- fatal("%s line %d: Bad mask.", filename, linenum);
+ fatal("%s line %d: Invalid %s.",
+ filename, linenum, keyword);
if (*activep)
options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
break;
@@ -2320,13 +2406,13 @@ process_server_config_line_depth(ServerOptions *options, char *line,
goto parse_flag;
case sFingerprintHash:
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.",
- filename, linenum);
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
if ((value = ssh_digest_alg_by_name(arg)) == -1)
- fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
- filename, linenum, arg);
+ fatal("%.200s line %d: Invalid %s algorithm \"%s\".",
+ filename, linenum, keyword, arg);
if (*activep)
options->fingerprint_hash = value;
break;
@@ -2341,13 +2427,13 @@ process_server_config_line_depth(ServerOptions *options, char *line,
"platform.", filename, linenum);
#endif
charptr = &options->routing_domain;
- arg = strdelim(&cp);
+ arg = argv_next(&ac, &av);
if (!arg || *arg == '\0')
- fatal("%.200s line %d: Missing argument.",
- filename, linenum);
+ fatal("%s line %d: %s missing argument.",
+ filename, linenum, keyword);
if (strcasecmp(arg, "none") != 0 && strcmp(arg, "%D") != 0 &&
!valid_rdomain(arg))
- fatal("%s line %d: bad routing domain",
+ fatal("%s line %d: invalid routing domain",
filename, linenum);
if (*activep && *charptr == NULL)
*charptr = xstrdup(arg);
@@ -2359,19 +2445,27 @@ process_server_config_line_depth(ServerOptions *options, char *line,
do_log2(opcode == sIgnore ?
SYSLOG_LEVEL_DEBUG2 : SYSLOG_LEVEL_INFO,
"%s line %d: %s option %s", filename, linenum,
- opcode == sUnsupported ? "Unsupported" : "Deprecated", arg);
- while (arg)
- arg = strdelim(&cp);
+ opcode == sUnsupported ? "Unsupported" : "Deprecated",
+ keyword);
+ argv_consume(&ac);
break;
default:
fatal("%s line %d: Missing handler for opcode %s (%d)",
- filename, linenum, arg, opcode);
+ filename, linenum, keyword, opcode);
}
- if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
- fatal("%s line %d: garbage at end of line; \"%.200s\".",
- filename, linenum, arg);
- return 0;
+ /* Check that there is no garbage at end of line. */
+ if (ac > 0) {
+ error("%.200s line %d: keyword %s extra arguments "
+ "at end of line", filename, linenum, keyword);
+ goto out;
+ }
+
+ /* success */
+ ret = 0;
+ out:
+ argv_free(oav, oac);
+ return ret;
}
int
@@ -2379,8 +2473,10 @@ process_server_config_line(ServerOptions *options, char *line,
const char *filename, int linenum, int *activep,
struct connection_info *connectinfo, struct include_list *includes)
{
+ int inc_flags = 0;
+
return process_server_config_line_depth(options, line, filename,
- linenum, activep, connectinfo, 0, 0, includes);
+ linenum, activep, connectinfo, &inc_flags, 0, includes);
}
@@ -2389,35 +2485,38 @@ process_server_config_line(ServerOptions *options, char *line,
void
load_server_config(const char *filename, struct sshbuf *conf)
{
+ struct stat st;
char *line = NULL, *cp;
size_t linesize = 0;
FILE *f;
int r, lineno = 0;
- debug2("%s: filename %s", __func__, filename);
+ debug2_f("filename %s", filename);
if ((f = fopen(filename, "r")) == NULL) {
perror(filename);
exit(1);
}
sshbuf_reset(conf);
+ /* grow buffer, so realloc is avoided for large config files */
+ if (fstat(fileno(f), &st) == 0 && st.st_size > 0 &&
+ (r = sshbuf_allocate(conf, st.st_size)) != 0)
+ fatal_fr(r, "allocate");
while (getline(&line, &linesize, f) != -1) {
lineno++;
/*
- * Trim out comments and strip whitespace
+ * Strip whitespace
* NB - preserve newlines, they are needed to reproduce
* line numbers later for error messages
*/
- if ((cp = strchr(line, '#')) != NULL)
- memcpy(cp, "\n", 2);
cp = line + strspn(line, " \t\r");
if ((r = sshbuf_put(conf, cp, strlen(cp))) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_put");
}
free(line);
if ((r = sshbuf_put_u8(conf, 0)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_put_u8");
fclose(f);
- debug2("%s: done config len = %zu", __func__, sshbuf_len(conf));
+ debug2_f("done config len = %zu", sshbuf_len(conf));
}
void
@@ -2461,12 +2560,12 @@ int parse_server_match_testspec(struct connection_info *ci, char *spec)
ci->lport = a2port(p + 6);
if (ci->lport == -1) {
fprintf(stderr, "Invalid port '%s' in test mode"
- " specification %s\n", p+6, p);
+ " specification %s\n", p+6, p);
return -1;
}
} else {
fprintf(stderr, "Invalid test mode specification %s\n",
- p);
+ p);
return -1;
}
}
@@ -2584,7 +2683,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
#undef M_CP_STRARRAYOPT
#define SERVCONF_MAX_DEPTH 16
-void
+static void
parse_server_config_depth(ServerOptions *options, const char *filename,
struct sshbuf *conf, struct include_list *includes,
struct connection_info *connectinfo, int flags, int *activep, int depth)
@@ -2595,14 +2694,15 @@ parse_server_config_depth(ServerOptions *options, const char *filename,
if (depth < 0 || depth > SERVCONF_MAX_DEPTH)
fatal("Too many recursive configuration includes");
- debug2("%s: config %s len %zu", __func__, filename, sshbuf_len(conf));
+ debug2_f("config %s len %zu%s", filename, sshbuf_len(conf),
+ (flags & SSHCFG_NEVERMATCH ? " [checking syntax only]" : ""));
if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL)
- fatal("%s: sshbuf_dup_string failed", __func__);
+ fatal_f("sshbuf_dup_string failed");
linenum = 1;
while ((cp = strsep(&cbuf, "\n")) != NULL) {
if (process_server_config_line_depth(options, cp,
- filename, linenum++, activep, connectinfo, flags,
+ filename, linenum++, activep, connectinfo, &flags,
depth, includes) != 0)
bad_options++;
}
@@ -2610,7 +2710,6 @@ parse_server_config_depth(ServerOptions *options, const char *filename,
if (bad_options > 0)
fatal("%s: terminating, %d bad configuration options",
filename, bad_options);
- process_queued_listen_addrs(options);
}
void
@@ -2620,7 +2719,8 @@ parse_server_config(ServerOptions *options, const char *filename,
{
int active = connectinfo ? 0 : 1;
parse_server_config_depth(options, filename, conf, includes,
- connectinfo, 0, &active, 0);
+ connectinfo, (connectinfo ? SSHCFG_MATCH_ONLY : 0), &active, 0);
+ process_queued_listen_addrs(options);
}
static const char *
@@ -2809,8 +2909,6 @@ dump_config(ServerOptions *o)
dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
dump_cfg_fmtint(sKbdInteractiveAuthentication,
o->kbd_interactive_authentication);
- dump_cfg_fmtint(sChallengeResponseAuthentication,
- o->challenge_response_authentication);
dump_cfg_fmtint(sPrintMotd, o->print_motd);
#ifndef DISABLE_LASTLOG
dump_cfg_fmtint(sPrintLastLog, o->print_lastlog);
@@ -2835,6 +2933,7 @@ dump_config(ServerOptions *o)
/* string arguments */
dump_cfg_string(sPidFile, o->pid_file);
+ dump_cfg_string(sModuliFile, o->moduli_file);
dump_cfg_string(sXAuthLocation, o->xauth_location);
dump_cfg_string(sCiphers, o->ciphers);
dump_cfg_string(sMacs, o->macs);
@@ -2855,9 +2954,9 @@ dump_config(ServerOptions *o)
dump_cfg_string(sHostKeyAgent, o->host_key_agent);
dump_cfg_string(sKexAlgorithms, o->kex_algorithms);
dump_cfg_string(sCASignatureAlgorithms, o->ca_sign_algorithms);
- dump_cfg_string(sHostbasedAcceptedKeyTypes, o->hostbased_key_types);
+ dump_cfg_string(sHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
dump_cfg_string(sHostKeyAlgorithms, o->hostkeyalgorithms);
- dump_cfg_string(sPubkeyAcceptedKeyTypes, o->pubkey_key_types);
+ dump_cfg_string(sPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
#if defined(__OpenBSD__) || defined(HAVE_SYS_SET_PROCESS_RDOMAIN)
dump_cfg_string(sRDomain, o->routing_domain);
#endif
@@ -2870,9 +2969,9 @@ dump_config(ServerOptions *o)
dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files,
o->authorized_keys_files);
dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
- o->host_key_files);
+ o->host_key_files);
dump_cfg_strarray(sHostCertificate, o->num_host_cert_files,
- o->host_cert_files);
+ o->host_cert_files);
dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users);
dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users);
dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
@@ -2881,6 +2980,8 @@ dump_config(ServerOptions *o)
dump_cfg_strarray(sSetEnv, o->num_setenv, o->setenv);
dump_cfg_strarray_oneline(sAuthenticationMethods,
o->num_auth_methods, o->auth_methods);
+ dump_cfg_strarray_oneline(sLogVerbose,
+ o->num_log_verbose, o->log_verbose);
/* other arguments */
for (i = 0; i < o->num_subsystems; i++)
@@ -2889,6 +2990,13 @@ dump_config(ServerOptions *o)
printf("maxstartups %d:%d:%d\n", o->max_startups_begin,
o->max_startups_rate, o->max_startups);
+ printf("persourcemaxstartups ");
+ if (o->per_source_max_startups == INT_MAX)
+ printf("none\n");
+ else
+ printf("%d\n", o->per_source_max_startups);
+ printf("persourcenetblocksize %d:%d\n", o->per_source_masklen_ipv4,
+ o->per_source_masklen_ipv6);
s = NULL;
for (i = 0; tunmode_desc[i].val != -1; i++) {
@@ -2922,11 +3030,11 @@ dump_config(ServerOptions *o)
}
printf("\n");
- if (o->permit_user_env_whitelist == NULL) {
+ if (o->permit_user_env_allowlist == NULL) {
dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
} else {
printf("permituserenvironment %s\n",
- o->permit_user_env_whitelist);
+ o->permit_user_env_allowlist);
}
printf("pubkeyauthoptions");
@@ -2934,5 +3042,7 @@ dump_config(ServerOptions *o)
printf(" none");
if (o->pubkey_auth_options & PUBKEYAUTH_TOUCH_REQUIRED)
printf(" touch-required");
+ if (o->pubkey_auth_options & PUBKEYAUTH_VERIFY_REQUIRED)
+ printf(" verify-required");
printf("\n");
}
diff --git a/servconf.h b/servconf.h
index a420f398d..dd5cbc15c 100644
--- a/servconf.h
+++ b/servconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.h,v 1.144 2020/04/17 03:30:05 djm Exp $ */
+/* $OpenBSD: servconf.h,v 1.155 2021/07/02 05:11:21 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -50,7 +50,8 @@
#define INTERNAL_SFTP_NAME "internal-sftp"
/* PubkeyAuthOptions flags */
-#define PUBKEYAUTH_TOUCH_REQUIRED 1
+#define PUBKEYAUTH_TOUCH_REQUIRED (1)
+#define PUBKEYAUTH_VERIFY_REQUIRED (1<<1)
struct ssh;
struct fwd_perm_list;
@@ -92,6 +93,7 @@ typedef struct {
char *host_key_agent; /* ssh-agent socket for host keys. */
char *pid_file; /* Where to put our pid */
+ char *moduli_file; /* moduli file for DH-GEX */
int login_grace_time; /* Disconnect if no auth in this time
* (sec). */
int permit_root_login; /* PERMIT_*, see above */
@@ -117,13 +119,15 @@ typedef struct {
struct ForwardOptions fwd_opts; /* forwarding options */
SyslogFacility log_facility; /* Facility for system logging. */
LogLevel log_level; /* Level for system logging. */
+ u_int num_log_verbose; /* Verbose log overrides */
+ char **log_verbose;
int hostbased_authentication; /* If true, permit ssh2 hostbased auth */
int hostbased_uses_name_from_packet_only; /* experimental */
- char *hostbased_key_types; /* Key types allowed for hostbased */
+ char *hostbased_accepted_algos; /* Algos allowed for hostbased */
char *hostkeyalgorithms; /* SSH2 server key types */
char *ca_sign_algorithms; /* Allowed CA signature algorithms */
int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */
- char *pubkey_key_types; /* Key types allowed for public key */
+ char *pubkey_accepted_algos; /* Signature algos allowed for pubkey */
int pubkey_auth_options; /* -1 or mask of PUBKEYAUTH_* flags */
int kerberos_authentication; /* If true, permit Kerberos
* authentication. */
@@ -142,11 +146,10 @@ typedef struct {
int password_authentication; /* If true, permit password
* authentication. */
int kbd_interactive_authentication; /* If true, permit */
- int challenge_response_authentication;
int permit_empty_passwd; /* If false, do not permit empty
* passwords. */
int permit_user_env; /* If true, read ~/.ssh/environment */
- char *permit_user_env_whitelist; /* pattern-list whitelist */
+ char *permit_user_env_allowlist; /* pattern-list of allowed env names */
int compression; /* If true, compression is allowed */
int allow_tcp_forwarding; /* One of FORWARD_* */
int allow_streamlocal_forwarding; /* One of FORWARD_* */
@@ -174,6 +177,9 @@ typedef struct {
int max_startups_begin;
int max_startups_rate;
int max_startups;
+ int per_source_max_startups;
+ int per_source_masklen_ipv4;
+ int per_source_masklen_ipv6;
int max_authtries;
int max_sessions;
char *banner; /* SSH-2 banner message */
@@ -229,7 +235,7 @@ typedef struct {
struct connection_info {
const char *user;
const char *host; /* possibly resolved hostname */
- const char *address; /* remote address */
+ const char *address; /* remote address */
const char *laddress; /* local address */
int lport; /* local port */
const char *rdomain; /* routing domain if available */
@@ -250,7 +256,7 @@ TAILQ_HEAD(include_list, include_item);
/*
* These are string config options that must be copied between the
* Match sub-config and the main config, and must be sent from the
- * privsep slave to the privsep master. We use a macro to ensure all
+ * privsep child to the privsep master. We use a macro to ensure all
* the options are copied and the copies are done in the correct order.
*
* NB. an option must appear in servconf.c:copy_set_server_options() or
@@ -265,33 +271,35 @@ TAILQ_HEAD(include_list, include_item);
M_CP_STROPT(authorized_principals_file); \
M_CP_STROPT(authorized_principals_command); \
M_CP_STROPT(authorized_principals_command_user); \
- M_CP_STROPT(hostbased_key_types); \
- M_CP_STROPT(pubkey_key_types); \
+ M_CP_STROPT(hostbased_accepted_algos); \
+ M_CP_STROPT(pubkey_accepted_algos); \
M_CP_STROPT(ca_sign_algorithms); \
M_CP_STROPT(routing_domain); \
- M_CP_STROPT(permit_user_env_whitelist); \
+ M_CP_STROPT(permit_user_env_allowlist); \
M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \
M_CP_STRARRAYOPT(allow_users, num_allow_users); \
M_CP_STRARRAYOPT(deny_users, num_deny_users); \
M_CP_STRARRAYOPT(allow_groups, num_allow_groups); \
M_CP_STRARRAYOPT(deny_groups, num_deny_groups); \
M_CP_STRARRAYOPT(accept_env, num_accept_env); \
+ M_CP_STRARRAYOPT(setenv, num_setenv); \
M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \
M_CP_STRARRAYOPT(permitted_opens, num_permitted_opens); \
M_CP_STRARRAYOPT(permitted_listens, num_permitted_listens); \
+ M_CP_STRARRAYOPT(log_verbose, num_log_verbose); \
} while (0)
struct connection_info *get_connection_info(struct ssh *, int, int);
void initialize_server_options(ServerOptions *);
void fill_default_server_options(ServerOptions *);
int process_server_config_line(ServerOptions *, char *, const char *, int,
- int *, struct connection_info *, struct include_list *includes);
+ int *, struct connection_info *, struct include_list *includes);
void process_permitopen(struct ssh *ssh, ServerOptions *options);
void load_server_config(const char *, struct sshbuf *);
void parse_server_config(ServerOptions *, const char *, struct sshbuf *,
- struct include_list *includes, struct connection_info *);
+ struct include_list *includes, struct connection_info *);
void parse_server_match_config(ServerOptions *,
- struct include_list *includes, struct connection_info *);
+ struct include_list *includes, struct connection_info *);
int parse_server_match_testspec(struct connection_info *, char *);
int server_match_spec_complete(struct connection_info *);
void copy_set_server_options(ServerOptions *, ServerOptions *, int);
diff --git a/serverloop.c b/serverloop.c
index 340b19a5a..e8cfb9205 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: serverloop.c,v 1.222 2020/01/30 07:21:38 djm Exp $ */
+/* $OpenBSD: serverloop.c,v 1.228 2021/07/16 09:00:23 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -88,11 +88,6 @@ extern int use_privsep;
static int no_more_sessions = 0; /* Disallow further sessions. */
-/*
- * This SIGCHLD kludge is used to detect when the child exits. The server
- * will exit after that, as soon as forwarded connections have terminated.
- */
-
static volatile sig_atomic_t child_terminated = 0; /* The child has terminated. */
/* Cleanup on signals (!use_privsep case only) */
@@ -115,59 +110,11 @@ bind_permitted(int port, uid_t uid)
return 1;
}
-/*
- * we write to this pipe if a SIGCHLD is caught in order to avoid
- * the race between select() and child_terminated
- */
-static int notify_pipe[2];
-static void
-notify_setup(void)
-{
- if (pipe(notify_pipe) == -1) {
- error("pipe(notify_pipe) failed %s", strerror(errno));
- } else if ((fcntl(notify_pipe[0], F_SETFD, FD_CLOEXEC) == -1) ||
- (fcntl(notify_pipe[1], F_SETFD, FD_CLOEXEC) == -1)) {
- error("fcntl(notify_pipe, F_SETFD) failed %s", strerror(errno));
- close(notify_pipe[0]);
- close(notify_pipe[1]);
- } else {
- set_nonblock(notify_pipe[0]);
- set_nonblock(notify_pipe[1]);
- return;
- }
- notify_pipe[0] = -1; /* read end */
- notify_pipe[1] = -1; /* write end */
-}
-static void
-notify_parent(void)
-{
- if (notify_pipe[1] != -1)
- (void)write(notify_pipe[1], "", 1);
-}
-static void
-notify_prepare(fd_set *readset)
-{
- if (notify_pipe[0] != -1)
- FD_SET(notify_pipe[0], readset);
-}
-static void
-notify_done(fd_set *readset)
-{
- char c;
-
- if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset))
- while (read(notify_pipe[0], &c, 1) != -1)
- debug2("%s: reading", __func__);
-}
-
/*ARGSUSED*/
static void
sigchld_handler(int sig)
{
- int save_errno = errno;
child_terminated = 1;
- notify_parent();
- errno = save_errno;
}
/*ARGSUSED*/
@@ -201,18 +148,18 @@ client_alive_check(struct ssh *ssh)
(r = sshpkt_put_cstring(ssh, "keepalive@openssh.com"))
!= 0 ||
(r = sshpkt_put_u8(ssh, 1)) != 0) /* boolean: want reply */
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
} else {
channel_request_start(ssh, channel_id,
"keepalive@openssh.com", 1);
}
if ((r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send");
}
/*
- * Sleep in select() until we can do something. This will initialize the
- * select masks. Upon return, the masks will indicate which descriptors
+ * Sleep in pselect() until we can do something. This will initialize the
+ * pselect masks. Upon return, the masks will indicate which descriptors
* have data or can accept data. Optionally, a maximum time can be specified
* for the duration of the wait (0 = infinite).
*/
@@ -220,16 +167,16 @@ static void
wait_until_can_do_something(struct ssh *ssh,
int connection_in, int connection_out,
fd_set **readsetp, fd_set **writesetp, int *maxfdp,
- u_int *nallocp, u_int64_t max_time_ms)
+ u_int *nallocp, u_int64_t max_time_ms, sigset_t *sigsetp)
{
- struct timeval tv, *tvp;
+ struct timespec ts, *tsp;
int ret;
time_t minwait_secs = 0;
int client_alive_scheduled = 0;
/* time we last heard from the client OR sent a keepalive */
static time_t last_client_time;
- /* Allocate and update select() masks for channel descriptors. */
+ /* Allocate and update pselect() masks for channel descriptors. */
channel_prepare_select(ssh, readsetp, writesetp, maxfdp,
nallocp, &minwait_secs);
@@ -253,6 +200,8 @@ wait_until_can_do_something(struct ssh *ssh,
max_time_ms = keepalive_ms;
client_alive_scheduled = 1;
}
+ if (last_client_time == 0)
+ last_client_time = monotime();
}
#if 0
@@ -260,7 +209,6 @@ wait_until_can_do_something(struct ssh *ssh,
if (channel_not_very_much_buffered_data())
#endif
FD_SET(connection_in, *readsetp);
- notify_prepare(*readsetp);
/*
* If we have buffered packet data going to the client, mark that
@@ -278,26 +226,26 @@ wait_until_can_do_something(struct ssh *ssh,
max_time_ms = 100;
if (max_time_ms == 0)
- tvp = NULL;
+ tsp = NULL;
else {
- tv.tv_sec = max_time_ms / 1000;
- tv.tv_usec = 1000 * (max_time_ms % 1000);
- tvp = &tv;
+ ts.tv_sec = max_time_ms / 1000;
+ ts.tv_nsec = 1000000 * (max_time_ms % 1000);
+ tsp = &ts;
}
/* Wait for something to happen, or the timeout to expire. */
- ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
+ ret = pselect((*maxfdp)+1, *readsetp, *writesetp, NULL, tsp, sigsetp);
if (ret == -1) {
memset(*readsetp, 0, *nallocp);
memset(*writesetp, 0, *nallocp);
if (errno != EINTR)
- error("select: %.100s", strerror(errno));
+ error("pselect: %.100s", strerror(errno));
} else if (client_alive_scheduled) {
time_t now = monotime();
/*
- * If the select timed out, or returned for some other reason
+ * If the pselect timed out, or returned for some other reason
* but we haven't heard from the client in time, send keepalive.
*/
if (ret == 0 || (last_client_time != 0 && last_client_time +
@@ -308,8 +256,6 @@ wait_until_can_do_something(struct ssh *ssh,
last_client_time = now;
}
}
-
- notify_done(*readsetp);
}
/*
@@ -330,21 +276,17 @@ process_input(struct ssh *ssh, fd_set *readset, int connection_in)
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
return -1;
} else if (len == -1) {
- if (errno != EINTR && errno != EAGAIN &&
- errno != EWOULDBLOCK) {
- verbose("Read error from remote host "
- "%.100s port %d: %.100s",
- ssh_remote_ipaddr(ssh),
- ssh_remote_port(ssh), strerror(errno));
- cleanup_exit(255);
- }
- } else {
- /* Buffer any received data. */
- if ((r = ssh_packet_process_incoming(ssh, buf, len))
- != 0)
- fatal("%s: ssh_packet_process_incoming: %s",
- __func__, ssh_err(r));
+ if (errno == EINTR || errno == EAGAIN ||
+ errno == EWOULDBLOCK)
+ return 0;
+ verbose("Read error from remote host %s port %d: %s",
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
+ strerror(errno));
+ cleanup_exit(255);
}
+ /* Buffer any received data. */
+ if ((r = ssh_packet_process_incoming(ssh, buf, len)) != 0)
+ fatal_fr(r, "ssh_packet_process_incoming");
}
return 0;
}
@@ -376,13 +318,8 @@ static void
collect_children(struct ssh *ssh)
{
pid_t pid;
- sigset_t oset, nset;
int status;
- /* block SIGCHLD while we check for dead children */
- sigemptyset(&nset);
- sigaddset(&nset, SIGCHLD);
- sigprocmask(SIG_BLOCK, &nset, &oset);
if (child_terminated) {
debug("Received SIGCHLD.");
while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
@@ -391,19 +328,21 @@ collect_children(struct ssh *ssh)
session_close_by_pid(ssh, pid, status);
child_terminated = 0;
}
- sigprocmask(SIG_SETMASK, &oset, NULL);
}
void
server_loop2(struct ssh *ssh, Authctxt *authctxt)
{
fd_set *readset = NULL, *writeset = NULL;
- int max_fd;
+ int r, max_fd;
u_int nalloc = 0, connection_in, connection_out;
u_int64_t rekey_timeout_ms = 0;
+ sigset_t bsigset, osigset;
debug("Entering interactive session for SSH2.");
+ if (sigemptyset(&bsigset) == -1 || sigaddset(&bsigset, SIGCHLD) == -1)
+ error_f("bsigset setup: %s", strerror(errno));
ssh_signal(SIGCHLD, sigchld_handler);
child_terminated = 0;
connection_in = ssh_packet_get_connection_in(ssh);
@@ -415,10 +354,7 @@ server_loop2(struct ssh *ssh, Authctxt *authctxt)
ssh_signal(SIGQUIT, sigterm_handler);
}
- notify_setup();
-
max_fd = MAXIMUM(connection_in, connection_out);
- max_fd = MAXIMUM(max_fd, notify_pipe[0]);
server_init_dispatch(ssh);
@@ -436,8 +372,19 @@ server_loop2(struct ssh *ssh, Authctxt *authctxt)
rekey_timeout_ms = 0;
}
+ /*
+ * Block SIGCHLD while we check for dead children, then pass
+ * the old signal mask through to pselect() so that it'll wake
+ * up immediately if a child exits after we've called waitpid().
+ */
+ if (sigprocmask(SIG_BLOCK, &bsigset, &osigset) == -1)
+ error_f("bsigset sigprocmask: %s", strerror(errno));
+ collect_children(ssh);
wait_until_can_do_something(ssh, connection_in, connection_out,
- &readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms);
+ &readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms,
+ &osigset);
+ if (sigprocmask(SIG_UNBLOCK, &bsigset, &osigset) == -1)
+ error_f("osigset sigprocmask: %s", strerror(errno));
if (received_sigterm) {
logit("Exiting on signal %d", (int)received_sigterm);
@@ -445,11 +392,13 @@ server_loop2(struct ssh *ssh, Authctxt *authctxt)
cleanup_exit(255);
}
- collect_children(ssh);
if (!ssh_packet_is_rekeying(ssh))
channel_after_select(ssh, readset, writeset);
if (process_input(ssh, readset, connection_in) < 0)
break;
+ /* A timeout may have triggered rekeying */
+ if ((r = ssh_packet_check_rekey(ssh)) != 0)
+ fatal_fr(r, "cannot start rekeying");
process_output(ssh, writeset, connection_out);
}
collect_children(ssh);
@@ -492,17 +441,17 @@ server_request_direct_tcpip(struct ssh *ssh, int *reason, const char **errmsg)
(r = sshpkt_get_end(ssh)) != 0)
sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
if (target_port > 0xFFFF) {
- error("%s: invalid target port", __func__);
+ error_f("invalid target port");
*reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
goto out;
}
if (originator_port > 0xFFFF) {
- error("%s: invalid originator port", __func__);
+ error_f("invalid originator port");
*reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
goto out;
}
- debug("%s: originator %s port %u, target %s port %u", __func__,
+ debug_f("originator %s port %u, target %s port %u",
originator, originator_port, target, target_port);
/* XXX fine grained permissions */
@@ -535,7 +484,7 @@ server_request_direct_streamlocal(struct ssh *ssh)
int r;
if (pw == NULL || !the_authctxt->valid)
- fatal("%s: no/invalid user", __func__);
+ fatal_f("no/invalid user");
if ((r = sshpkt_get_cstring(ssh, &target, NULL)) != 0 ||
(r = sshpkt_get_cstring(ssh, &originator, NULL)) != 0 ||
@@ -543,11 +492,11 @@ server_request_direct_streamlocal(struct ssh *ssh)
(r = sshpkt_get_end(ssh)) != 0)
sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
if (originator_port > 0xFFFF) {
- error("%s: invalid originator port", __func__);
+ error_f("invalid originator port");
goto out;
}
- debug("%s: originator %s port %d, target %s", __func__,
+ debug_f("originator %s port %d, target %s",
originator, originator_port, target);
/* XXX fine grained permissions */
@@ -595,7 +544,7 @@ server_request_tun(struct ssh *ssh)
if ((r = sshpkt_get_u32(ssh, &tun)) != 0)
sshpkt_fatal(ssh, r, "%s: parse device", __func__);
if (tun > INT_MAX) {
- debug("%s: invalid tun", __func__);
+ debug_f("invalid tun");
goto done;
}
if (auth_opts->force_tun_device != -1) {
@@ -684,7 +633,7 @@ server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
(r = sshpkt_get_u32(ssh, &rwindow)) != 0 ||
(r = sshpkt_get_u32(ssh, &rmaxpack)) != 0)
sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
- debug("%s: ctype %s rchan %u win %u max %u", __func__,
+ debug_f("ctype %s rchan %u win %u max %u",
ctype, rchan, rwindow, rmaxpack);
if (strcmp(ctype, "session") == 0) {
@@ -697,7 +646,7 @@ server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
c = server_request_tun(ssh);
}
if (c != NULL) {
- debug("%s: confirm %s", __func__, ctype);
+ debug_f("confirm %s", ctype);
c->remote_id = rchan;
c->have_remote_id = 1;
c->remote_window = rwindow;
@@ -714,7 +663,7 @@ server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
}
}
} else {
- debug("%s: failure %s", __func__, ctype);
+ debug_f("failure %s", ctype);
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 ||
(r = sshpkt_put_u32(ssh, rchan)) != 0 ||
(r = sshpkt_put_u32(ssh, reason)) != 0 ||
@@ -741,7 +690,7 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp)
size_t blen, slen;
if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
kexsigtype = sshkey_type_plain(
sshkey_type_from_name(ssh->kex->hostkey_alg));
@@ -750,8 +699,7 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp)
key = NULL;
if ((r = sshpkt_get_string_direct(ssh, &blob, &blen)) != 0 ||
(r = sshkey_from_blob(blob, blen, &key)) != 0) {
- error("%s: couldn't parse key: %s",
- __func__, ssh_err(r));
+ error_fr(r, "parse key");
goto out;
}
/*
@@ -759,8 +707,7 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp)
* before attempting to sign anything with it.
*/
if ((ndx = ssh->kex->host_key_index(key, 1, ssh)) == -1) {
- error("%s: unknown host %s key",
- __func__, sshkey_type(key));
+ error_f("unknown host %s key", sshkey_type(key));
goto out;
}
/*
@@ -769,7 +716,7 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp)
*/
if ((key_prv = get_hostkey_by_index(ndx)) == NULL &&
(key_pub = get_hostkey_public_by_index(ndx, ssh)) == NULL) {
- error("%s: can't retrieve hostkey %d", __func__, ndx);
+ error_f("can't retrieve hostkey %d", ndx);
goto out;
}
sshbuf_reset(sigbuf);
@@ -783,15 +730,14 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp)
sshkey_type_plain(key->type) == KEY_RSA;
if ((r = sshbuf_put_cstring(sigbuf,
"hostkeys-prove-00@openssh.com")) != 0 ||
- (r = sshbuf_put_string(sigbuf,
- ssh->kex->session_id, ssh->kex->session_id_len)) != 0 ||
+ (r = sshbuf_put_stringb(sigbuf,
+ ssh->kex->session_id)) != 0 ||
(r = sshkey_puts(key, sigbuf)) != 0 ||
(r = ssh->kex->sign(ssh, key_prv, key_pub, &sig, &slen,
sshbuf_ptr(sigbuf), sshbuf_len(sigbuf),
use_kexsigtype ? ssh->kex->hostkey_alg : NULL)) != 0 ||
(r = sshbuf_put_string(resp, sig, slen)) != 0) {
- error("%s: couldn't prepare signature: %s",
- __func__, ssh_err(r));
+ error_fr(r, "assemble signature");
goto out;
}
}
@@ -820,19 +766,19 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
memset(&fwd, 0, sizeof(fwd));
if (pw == NULL || !the_authctxt->valid)
- fatal("%s: no/invalid user", __func__);
+ fatal_f("no/invalid user");
if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 ||
(r = sshpkt_get_u8(ssh, &want_reply)) != 0)
sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
- debug("%s: rtype %s want_reply %d", __func__, rtype, want_reply);
+ debug_f("rtype %s want_reply %d", rtype, want_reply);
/* -R style forwarding */
if (strcmp(rtype, "tcpip-forward") == 0) {
if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 ||
(r = sshpkt_get_u32(ssh, &port)) != 0)
sshpkt_fatal(ssh, r, "%s: parse tcpip-forward", __func__);
- debug("%s: tcpip-forward listen %s port %u", __func__,
+ debug_f("tcpip-forward listen %s port %u",
fwd.listen_host, port);
if (port <= INT_MAX)
fwd.listen_port = (int)port;
@@ -843,7 +789,7 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
options.disable_forwarding ||
(!want_reply && fwd.listen_port == 0) ||
(fwd.listen_port != 0 &&
- !bind_permitted(fwd.listen_port, pw->pw_uid))) {
+ !bind_permitted(fwd.listen_port, pw->pw_uid))) {
success = 0;
ssh_packet_send_debug(ssh, "Server has disabled port forwarding.");
} else {
@@ -852,16 +798,16 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
&allocated_listen_port, &options.fwd_opts);
}
if ((resp = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
if (allocated_listen_port != 0 &&
(r = sshbuf_put_u32(resp, allocated_listen_port)) != 0)
- fatal("%s: sshbuf_put_u32: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_put_u32");
} else if (strcmp(rtype, "cancel-tcpip-forward") == 0) {
if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 ||
(r = sshpkt_get_u32(ssh, &port)) != 0)
sshpkt_fatal(ssh, r, "%s: parse cancel-tcpip-forward", __func__);
- debug("%s: cancel-tcpip-forward addr %s port %d", __func__,
+ debug_f("cancel-tcpip-forward addr %s port %d",
fwd.listen_host, port);
if (port <= INT_MAX) {
fwd.listen_port = (int)port;
@@ -870,7 +816,7 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
} else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) {
if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0)
sshpkt_fatal(ssh, r, "%s: parse streamlocal-forward@openssh.com", __func__);
- debug("%s: streamlocal-forward listen path %s", __func__,
+ debug_f("streamlocal-forward listen path %s",
fwd.listen_path);
/* check permissions */
@@ -889,7 +835,7 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
} else if (strcmp(rtype, "cancel-streamlocal-forward@openssh.com") == 0) {
if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0)
sshpkt_fatal(ssh, r, "%s: parse cancel-streamlocal-forward@openssh.com", __func__);
- debug("%s: cancel-streamlocal-forward path %s", __func__,
+ debug_f("cancel-streamlocal-forward path %s",
fwd.listen_path);
success = channel_cancel_rport_listener(ssh, &fwd);
@@ -945,8 +891,7 @@ server_input_channel_req(int type, u_int32_t seq, struct ssh *ssh)
success = session_input_channel_req(ssh, c, rtype);
if (want_reply && !(c->flags & CHAN_CLOSE_SENT)) {
if (!c->have_remote_id)
- fatal("%s: channel %d: no remote_id",
- __func__, c->self);
+ fatal_f("channel %d: no remote_id", c->self);
if ((r = sshpkt_start(ssh, success ?
SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
diff --git a/session.c b/session.c
index 449b84c50..f9432bbcf 100644
--- a/session.c
+++ b/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.319 2020/03/13 03:17:07 djm Exp $ */
+/* $OpenBSD: session.c,v 1.329 2021/08/11 05:20:17 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@@ -253,7 +253,7 @@ display_loginmsg(void)
if (sshbuf_len(loginmsg) == 0)
return;
if ((r = sshbuf_put_u8(loginmsg, 0)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_put_u8");
printf("%s", (char *)sshbuf_ptr(loginmsg));
sshbuf_reset(loginmsg);
}
@@ -269,16 +269,16 @@ prepare_auth_info_file(struct passwd *pw, struct sshbuf *info)
temporarily_use_uid(pw);
auth_info_file = xstrdup("/tmp/sshauth.XXXXXXXXXXXXXXX");
if ((fd = mkstemp(auth_info_file)) == -1) {
- error("%s: mkstemp: %s", __func__, strerror(errno));
+ error_f("mkstemp: %s", strerror(errno));
goto out;
}
if (atomicio(vwrite, fd, sshbuf_mutable_ptr(info),
sshbuf_len(info)) != sshbuf_len(info)) {
- error("%s: write: %s", __func__, strerror(errno));
+ error_f("write: %s", strerror(errno));
goto out;
}
if (close(fd) != 0) {
- error("%s: close: %s", __func__, strerror(errno));
+ error_f("close: %s", strerror(errno));
goto out;
}
success = 1;
@@ -305,11 +305,10 @@ set_fwdpermit_from_authopts(struct ssh *ssh, const struct sshauthopt *opts)
tmp = cp = xstrdup(auth_opts->permitopen[i]);
/* This shouldn't fail as it has already been checked */
if ((host = hpdelim(&cp)) == NULL)
- fatal("%s: internal error: hpdelim", __func__);
+ fatal_f("internal error: hpdelim");
host = cleanhostname(host);
if (cp == NULL || (port = permitopen_port(cp)) < 0)
- fatal("%s: internal error: permitopen port",
- __func__);
+ fatal_f("internal error: permitopen port");
channel_add_permission(ssh,
FORWARD_USER, FORWARD_LOCAL, host, port);
free(tmp);
@@ -321,11 +320,10 @@ set_fwdpermit_from_authopts(struct ssh *ssh, const struct sshauthopt *opts)
tmp = cp = xstrdup(auth_opts->permitlisten[i]);
/* This shouldn't fail as it has already been checked */
if ((host = hpdelim(&cp)) == NULL)
- fatal("%s: internal error: hpdelim", __func__);
+ fatal_f("internal error: hpdelim");
host = cleanhostname(host);
if (cp == NULL || (port = permitopen_port(cp)) < 0)
- fatal("%s: internal error: permitlisten port",
- __func__);
+ fatal_f("internal error: permitlisten port");
channel_add_permission(ssh,
FORWARD_USER, FORWARD_REMOTE, host, port);
free(tmp);
@@ -400,18 +398,17 @@ do_exec_no_pty(struct ssh *ssh, Session *s, const char *command)
/* Allocate pipes for communicating with the program. */
if (pipe(pin) == -1) {
- error("%s: pipe in: %.100s", __func__, strerror(errno));
+ error_f("pipe in: %.100s", strerror(errno));
return -1;
}
if (pipe(pout) == -1) {
- error("%s: pipe out: %.100s", __func__, strerror(errno));
+ error_f("pipe out: %.100s", strerror(errno));
close(pin[0]);
close(pin[1]);
return -1;
}
if (pipe(perr) == -1) {
- error("%s: pipe err: %.100s", __func__,
- strerror(errno));
+ error_f("pipe err: %.100s", strerror(errno));
close(pin[0]);
close(pin[1]);
close(pout[0]);
@@ -426,12 +423,11 @@ do_exec_no_pty(struct ssh *ssh, Session *s, const char *command)
/* Uses socket pairs to communicate with the program. */
if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) == -1) {
- error("%s: socketpair #1: %.100s", __func__, strerror(errno));
+ error_f("socketpair #1: %.100s", strerror(errno));
return -1;
}
if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) == -1) {
- error("%s: socketpair #2: %.100s", __func__,
- strerror(errno));
+ error_f("socketpair #2: %.100s", strerror(errno));
close(inout[0]);
close(inout[1]);
return -1;
@@ -443,7 +439,7 @@ do_exec_no_pty(struct ssh *ssh, Session *s, const char *command)
/* Fork the child. */
switch ((pid = fork())) {
case -1:
- error("%s: fork: %.100s", __func__, strerror(errno));
+ error_f("fork: %.100s", strerror(errno));
#ifdef USE_PIPES
close(pin[0]);
close(pin[1]);
@@ -578,14 +574,14 @@ do_exec_pty(struct ssh *ssh, Session *s, const char *command)
* detect and gracefully fail out-of-fd conditions.
*/
if ((fdout = dup(ptyfd)) == -1) {
- error("%s: dup #1: %s", __func__, strerror(errno));
+ error_f("dup #1: %s", strerror(errno));
close(ttyfd);
close(ptyfd);
return -1;
}
/* we keep a reference to the pty master */
if ((ptymaster = dup(ptyfd)) == -1) {
- error("%s: dup #2: %s", __func__, strerror(errno));
+ error_f("dup #2: %s", strerror(errno));
close(ttyfd);
close(ptyfd);
close(fdout);
@@ -595,7 +591,7 @@ do_exec_pty(struct ssh *ssh, Session *s, const char *command)
/* Fork the child. */
switch ((pid = fork())) {
case -1:
- error("%s: fork: %.100s", __func__, strerror(errno));
+ error_f("fork: %.100s", strerror(errno));
close(fdout);
close(ptymaster);
close(ttyfd);
@@ -843,12 +839,12 @@ check_quietlogin(Session *s, const char *command)
* into the environment. If the file does not exist, this does nothing.
* Otherwise, it must consist of empty lines, comments (line starts with '#')
* and assignments of the form name=value. No other forms are allowed.
- * If whitelist is not NULL, then it is interpreted as a pattern list and
+ * If allowlist is not NULL, then it is interpreted as a pattern list and
* only variable names that match it will be accepted.
*/
static void
read_environment_file(char ***env, u_int *envsize,
- const char *filename, const char *whitelist)
+ const char *filename, const char *allowlist)
{
FILE *f;
char *line = NULL, *cp, *value;
@@ -881,8 +877,8 @@ read_environment_file(char ***env, u_int *envsize,
*/
*value = '\0';
value++;
- if (whitelist != NULL &&
- match_pattern_list(cp, whitelist, 0) != 1)
+ if (allowlist != NULL &&
+ match_pattern_list(cp, allowlist, 0) != 1)
continue;
child_set_env(env, envsize, cp, value);
}
@@ -924,7 +920,7 @@ read_etc_default_login(char ***env, u_int *envsize, uid_t uid)
* interested in.
*/
read_environment_file(&tmpenv, &tmpenvsize, "/etc/default/login",
- options.permit_user_env_whitelist);
+ options.permit_user_env_allowlist);
if (tmpenv == NULL)
return;
@@ -948,8 +944,8 @@ read_etc_default_login(char ***env, u_int *envsize, uid_t uid)
#if defined(USE_PAM) || defined(HAVE_CYGWIN)
static void
-copy_environment_blacklist(char **source, char ***env, u_int *envsize,
- const char *blacklist)
+copy_environment_denylist(char **source, char ***env, u_int *envsize,
+ const char *denylist)
{
char *var_name, *var_val;
int i;
@@ -965,8 +961,8 @@ copy_environment_blacklist(char **source, char ***env, u_int *envsize,
}
*var_val++ = '\0';
- if (blacklist == NULL ||
- match_pattern_list(var_name, blacklist, 0) != 1) {
+ if (denylist == NULL ||
+ match_pattern_list(var_name, denylist, 0) != 1) {
debug3("Copy environment: %s=%s", var_name, var_val);
child_set_env(env, envsize, var_name, var_val);
}
@@ -980,7 +976,7 @@ copy_environment_blacklist(char **source, char ***env, u_int *envsize,
static void
copy_environment(char **source, char ***env, u_int *envsize)
{
- copy_environment_blacklist(source, env, envsize, NULL);
+ copy_environment_denylist(source, env, envsize, NULL);
}
#endif
@@ -1093,7 +1089,7 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell)
if ((cp = getenv("AUTHSTATE")) != NULL)
child_set_env(&env, &envsize, "AUTHSTATE", cp);
read_environment_file(&env, &envsize, "/etc/environment",
- options.permit_user_env_whitelist);
+ options.permit_user_env_allowlist);
}
#endif
#ifdef KRB5
@@ -1111,12 +1107,12 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell)
for (n = 0 ; n < auth_opts->nenv; n++) {
ocp = xstrdup(auth_opts->env[n]);
cp = strchr(ocp, '=');
- if (*cp == '=') {
+ if (cp != NULL) {
*cp = '\0';
- /* Apply PermitUserEnvironment whitelist */
- if (options.permit_user_env_whitelist == NULL ||
+ /* Apply PermitUserEnvironment allowlist */
+ if (options.permit_user_env_allowlist == NULL ||
match_pattern_list(ocp,
- options.permit_user_env_whitelist, 0) == 1)
+ options.permit_user_env_allowlist, 0) == 1)
child_set_env(&env, &envsize,
ocp, cp + 1);
}
@@ -1126,10 +1122,10 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell)
/* read $HOME/.ssh/environment. */
if (options.permit_user_env) {
- snprintf(buf, sizeof buf, "%.200s/.ssh/environment",
- pw->pw_dir);
+ snprintf(buf, sizeof buf, "%.200s/%s/environment",
+ pw->pw_dir, _PATH_SSH_USER_DIR);
read_environment_file(&env, &envsize, buf,
- options.permit_user_env_whitelist);
+ options.permit_user_env_allowlist);
}
#ifdef USE_PAM
@@ -1144,15 +1140,15 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell)
* Don't allow PAM-internal env vars to leak
* back into the session environment.
*/
-#define PAM_ENV_BLACKLIST "SSH_AUTH_INFO*,SSH_CONNECTION*"
+#define PAM_ENV_DENYLIST "SSH_AUTH_INFO*,SSH_CONNECTION*"
p = fetch_pam_child_environment();
- copy_environment_blacklist(p, &env, &envsize,
- PAM_ENV_BLACKLIST);
+ copy_environment_denylist(p, &env, &envsize,
+ PAM_ENV_DENYLIST);
free_pam_environment(p);
p = fetch_pam_environment();
- copy_environment_blacklist(p, &env, &envsize,
- PAM_ENV_BLACKLIST);
+ copy_environment_denylist(p, &env, &envsize,
+ PAM_ENV_DENYLIST);
free_pam_environment(p);
}
#endif /* USE_PAM */
@@ -1208,19 +1204,21 @@ static void
do_rc_files(struct ssh *ssh, Session *s, const char *shell)
{
FILE *f = NULL;
- char cmd[1024];
+ char *cmd = NULL, *user_rc = NULL;
int do_xauth;
struct stat st;
do_xauth =
s->display != NULL && s->auth_proto != NULL && s->auth_data != NULL;
+ xasprintf(&user_rc, "%s/%s", s->pw->pw_dir, _PATH_SSH_USER_RC);
/* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */
if (!s->is_subsystem && options.adm_forced_command == NULL &&
auth_opts->permit_user_rc && options.permit_user_rc &&
- stat(_PATH_SSH_USER_RC, &st) >= 0) {
- snprintf(cmd, sizeof cmd, "%s -c '%s %s'",
- shell, _PATH_BSHELL, _PATH_SSH_USER_RC);
+ stat(user_rc, &st) >= 0) {
+ if (xasprintf(&cmd, "%s -c '%s %s'", shell, _PATH_BSHELL,
+ user_rc) == -1)
+ fatal_f("xasprintf: %s", strerror(errno));
if (debug_flag)
fprintf(stderr, "Running %s\n", cmd);
f = popen(cmd, "w");
@@ -1231,7 +1229,7 @@ do_rc_files(struct ssh *ssh, Session *s, const char *shell)
pclose(f);
} else
fprintf(stderr, "Could not run %s\n",
- _PATH_SSH_USER_RC);
+ user_rc);
} else if (stat(_PATH_SSH_SYSTEM_RC, &st) >= 0) {
if (debug_flag)
fprintf(stderr, "Running %s %s\n", _PATH_BSHELL,
@@ -1256,8 +1254,8 @@ do_rc_files(struct ssh *ssh, Session *s, const char *shell)
options.xauth_location, s->auth_display,
s->auth_proto, s->auth_data);
}
- snprintf(cmd, sizeof cmd, "%s -q -",
- options.xauth_location);
+ if (xasprintf(&cmd, "%s -q -", options.xauth_location) == -1)
+ fatal_f("xasprintf: %s", strerror(errno));
f = popen(cmd, "w");
if (f) {
fprintf(f, "remove %s\n",
@@ -1271,6 +1269,8 @@ do_rc_files(struct ssh *ssh, Session *s, const char *shell)
cmd);
}
}
+ free(cmd);
+ free(user_rc);
}
static void
@@ -1289,11 +1289,8 @@ do_nologin(struct passwd *pw)
return;
nl = def_nl;
#endif
- if (stat(nl, &sb) == -1) {
- if (nl != def_nl)
- free(nl);
+ if (stat(nl, &sb) == -1)
return;
- }
/* /etc/nologin exists. Print its contents if we can and exit. */
logit("User %.100s not allowed because %s exists", pw->pw_name, nl);
@@ -1334,10 +1331,10 @@ safely_chroot(const char *path, uid_t uid)
component[cp - path] = '\0';
}
- debug3("%s: checking '%s'", __func__, component);
+ debug3_f("checking '%s'", component);
if (stat(component, &st) != 0)
- fatal("%s: stat(\"%s\"): %s", __func__,
+ fatal_f("stat(\"%s\"): %s",
component, strerror(errno));
if (st.st_uid != 0 || (st.st_mode & 022) != 0)
fatal("bad ownership or modes for chroot "
@@ -1355,8 +1352,7 @@ safely_chroot(const char *path, uid_t uid)
if (chroot(path) == -1)
fatal("chroot(\"%s\"): %s", path, strerror(errno));
if (chdir("/") == -1)
- fatal("%s: chdir(/) after chroot: %s",
- __func__, strerror(errno));
+ fatal_f("chdir(/) after chroot: %s", strerror(errno));
verbose("Changed root directory to \"%s\"", path);
}
@@ -1394,7 +1390,7 @@ do_setusercontext(struct passwd *pw)
if (!in_chroot && options.chroot_directory != NULL &&
strcasecmp(options.chroot_directory, "none") != 0) {
- tmp = tilde_expand_filename(options.chroot_directory,
+ tmp = tilde_expand_filename(options.chroot_directory,
pw->pw_uid);
snprintf(uidstr, sizeof(uidstr), "%llu",
(unsigned long long)pw->pw_uid);
@@ -1499,6 +1495,9 @@ child_close_fds(struct ssh *ssh)
*/
endpwent();
+ /* Stop directing logs to a high-numbered fd before we close it */
+ log_redirect_stderr_to(NULL);
+
/*
* Close any extra open file descriptors so that we don't have them
* hanging around in clients. Note that we want to do this after
@@ -1722,11 +1721,11 @@ do_child(struct ssh *ssh, Session *s, const char *command)
void
session_unused(int id)
{
- debug3("%s: session id %d unused", __func__, id);
+ debug3_f("session id %d unused", id);
if (id >= options.max_sessions ||
id >= sessions_nalloc) {
- fatal("%s: insane session id %d (max %d nalloc %d)",
- __func__, id, options.max_sessions, sessions_nalloc);
+ fatal_f("insane session id %d (max %d nalloc %d)",
+ id, options.max_sessions, sessions_nalloc);
}
memset(&sessions[id], 0, sizeof(*sessions));
sessions[id].self = id;
@@ -1748,13 +1747,13 @@ session_new(void)
if (sessions_first_unused == -1) {
if (sessions_nalloc >= options.max_sessions)
return NULL;
- debug2("%s: allocate (allocated %d max %d)",
- __func__, sessions_nalloc, options.max_sessions);
+ debug2_f("allocate (allocated %d max %d)",
+ sessions_nalloc, options.max_sessions);
tmp = xrecallocarray(sessions, sessions_nalloc,
sessions_nalloc + 1, sizeof(*sessions));
if (tmp == NULL) {
- error("%s: cannot allocate %d sessions",
- __func__, sessions_nalloc + 1);
+ error_f("cannot allocate %d sessions",
+ sessions_nalloc + 1);
return NULL;
}
sessions = tmp;
@@ -1763,16 +1762,14 @@ session_new(void)
if (sessions_first_unused >= sessions_nalloc ||
sessions_first_unused < 0) {
- fatal("%s: insane first_unused %d max %d nalloc %d",
- __func__, sessions_first_unused, options.max_sessions,
+ fatal_f("insane first_unused %d max %d nalloc %d",
+ sessions_first_unused, options.max_sessions,
sessions_nalloc);
}
s = &sessions[sessions_first_unused];
- if (s->used) {
- fatal("%s: session %d already used",
- __func__, sessions_first_unused);
- }
+ if (s->used)
+ fatal_f("session %d already used", sessions_first_unused);
sessions_first_unused = s->next_unused;
s->used = 1;
s->next_unused = -1;
@@ -1788,12 +1785,11 @@ session_dump(void)
for (i = 0; i < sessions_nalloc; i++) {
Session *s = &sessions[i];
- debug("dump: used %d next_unused %d session %d %p "
+ debug("dump: used %d next_unused %d session %d "
"channel %d pid %ld",
s->used,
s->next_unused,
s->self,
- s,
s->chanid,
(long)s->pid);
}
@@ -2142,35 +2138,33 @@ session_signal_req(struct ssh *ssh, Session *s)
if ((r = sshpkt_get_cstring(ssh, &signame, NULL)) != 0 ||
(r = sshpkt_get_end(ssh)) != 0) {
- error("%s: parse packet: %s", __func__, ssh_err(r));
+ error_fr(r, "parse");
goto out;
}
if ((sig = name2sig(signame)) == -1) {
- error("%s: unsupported signal \"%s\"", __func__, signame);
+ error_f("unsupported signal \"%s\"", signame);
goto out;
}
if (s->pid <= 0) {
- error("%s: no pid for session %d", __func__, s->self);
+ error_f("no pid for session %d", s->self);
goto out;
}
if (s->forced || s->is_subsystem) {
- error("%s: refusing to send signal %s to %s session", __func__,
+ error_f("refusing to send signal %s to %s session",
signame, s->forced ? "forced-command" : "subsystem");
goto out;
}
if (!use_privsep || mm_is_monitor()) {
- error("%s: session signalling requires privilege separation",
- __func__);
+ error_f("session signalling requires privilege separation");
goto out;
}
- debug("%s: signal %s, killpg(%ld, %d)", __func__, signame,
- (long)s->pid, sig);
+ debug_f("signal %s, killpg(%ld, %d)", signame, (long)s->pid, sig);
temporarily_use_uid(s->pw);
r = killpg(s->pid, sig);
restore_uid();
if (r != 0) {
- error("%s: killpg(%ld, %d): %s", __func__, (long)s->pid,
+ error_f("killpg(%ld, %d): %s", (long)s->pid,
sig, strerror(errno));
goto out;
}
@@ -2192,7 +2186,7 @@ session_auth_agent_req(struct ssh *ssh, Session *s)
sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
if (!auth_opts->permit_agent_forwarding_flag ||
!options.allow_agent_forwarding) {
- debug("%s: agent forwarding disabled", __func__);
+ debug_f("agent forwarding disabled");
return 0;
}
if (called) {
@@ -2210,10 +2204,10 @@ session_input_channel_req(struct ssh *ssh, Channel *c, const char *rtype)
Session *s;
if ((s = session_by_channel(c->self)) == NULL) {
- logit("%s: no session %d req %.100s", __func__, c->self, rtype);
+ logit_f("no session %d req %.100s", c->self, rtype);
return 0;
}
- debug("%s: session %d req %s", __func__, s->self, rtype);
+ debug_f("session %d req %s", s->self, rtype);
/*
* a session is in LARVAL state until a shell, a command
@@ -2271,13 +2265,13 @@ void
session_pty_cleanup2(Session *s)
{
if (s == NULL) {
- error("%s: no session", __func__);
+ error_f("no session");
return;
}
if (s->ttyfd == -1)
return;
- debug("%s: session %d release %s", __func__, s->self, s->tty);
+ debug_f("session %d release %s", s->self, s->tty);
/* Record that the user has logged out. */
if (s->pid != 0)
@@ -2333,10 +2327,10 @@ session_close_x11(struct ssh *ssh, int id)
Channel *c;
if ((c = channel_by_id(ssh, id)) == NULL) {
- debug("%s: x11 channel %d missing", __func__, id);
+ debug_f("x11 channel %d missing", id);
} else {
/* Detach X11 listener */
- debug("%s: detach x11 channel %d", __func__, id);
+ debug_f("detach x11 channel %d", id);
channel_cancel_cleanup(ssh, id);
if (c->ostate != CHAN_OUTPUT_CLOSED)
chan_mark_dead(ssh, c);
@@ -2349,13 +2343,13 @@ session_close_single_x11(struct ssh *ssh, int id, void *arg)
Session *s;
u_int i;
- debug3("%s: channel %d", __func__, id);
+ debug3_f("channel %d", id);
channel_cancel_cleanup(ssh, id);
if ((s = session_by_x11_channel(id)) == NULL)
- fatal("%s: no x11 channel %d", __func__, id);
+ fatal_f("no x11 channel %d", id);
for (i = 0; s->x11_chanids[i] != -1; i++) {
- debug("%s: session %d: closing channel %d",
- __func__, s->self, s->x11_chanids[i]);
+ debug_f("session %d: closing channel %d",
+ s->self, s->x11_chanids[i]);
/*
* The channel "id" is already closing, but make sure we
* close all of its siblings.
@@ -2382,10 +2376,9 @@ session_exit_message(struct ssh *ssh, Session *s, int status)
int r;
if ((c = channel_lookup(ssh, s->chanid)) == NULL)
- fatal("%s: session %d: no channel %d",
- __func__, s->self, s->chanid);
- debug("%s: session %d channel %d pid %ld",
- __func__, s->self, s->chanid, (long)s->pid);
+ fatal_f("session %d: no channel %d", s->self, s->chanid);
+ debug_f("session %d channel %d pid %ld",
+ s->self, s->chanid, (long)s->pid);
if (WIFEXITED(status)) {
channel_request_start(ssh, s->chanid, "exit-status", 0);
@@ -2409,7 +2402,7 @@ session_exit_message(struct ssh *ssh, Session *s, int status)
}
/* disconnect channel */
- debug("%s: release channel %d", __func__, s->chanid);
+ debug_f("release channel %d", s->chanid);
/*
* Adjust cleanup callback attachment to send close messages when
@@ -2464,7 +2457,7 @@ session_close_by_pid(struct ssh *ssh, pid_t pid, int status)
{
Session *s = session_by_pid(pid);
if (s == NULL) {
- debug("%s: no session for pid %ld", __func__, (long)pid);
+ debug_f("no session for pid %ld", (long)pid);
return;
}
if (s->chanid != -1)
@@ -2485,13 +2478,12 @@ session_close_by_channel(struct ssh *ssh, int id, void *arg)
u_int i;
if (s == NULL) {
- debug("%s: no session for id %d", __func__, id);
+ debug_f("no session for id %d", id);
return;
}
- debug("%s: channel %d child %ld", __func__, id, (long)s->pid);
+ debug_f("channel %d child %ld", id, (long)s->pid);
if (s->pid != 0) {
- debug("%s: channel %d: has child, ttyfd %d",
- __func__, id, s->ttyfd);
+ debug_f("channel %d: has child, ttyfd %d", id, s->ttyfd);
/*
* delay detach of session, but release pty, since
* the fd's to the child are already closed
diff --git a/sftp-client.c b/sftp-client.c
index 72f7fff7a..9de9afa20 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-client.c,v 1.135 2019/10/04 04:31:59 djm Exp $ */
+/* $OpenBSD: sftp-client.c,v 1.155 2021/09/03 05:12:25 dtucker Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
@@ -37,6 +37,13 @@
#include <dirent.h>
#include <errno.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#else
+# ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+# endif
+#endif
#include <fcntl.h>
#include <signal.h>
#include <stdarg.h>
@@ -61,6 +68,12 @@
extern volatile sig_atomic_t interrupted;
extern int showprogress;
+/* Default size of buffer for up/download */
+#define DEFAULT_COPY_BUFLEN 32768
+
+/* Default number of concurrent outstanding requests */
+#define DEFAULT_NUM_REQUESTS 64
+
/* Minimum amount of data to read at a time */
#define MIN_READ_SIZE 512
@@ -77,7 +90,8 @@ extern int showprogress;
struct sftp_conn {
int fd_in;
int fd_out;
- u_int transfer_buflen;
+ u_int download_buflen;
+ u_int upload_buflen;
u_int num_requests;
u_int version;
u_int msg_id;
@@ -87,15 +101,52 @@ struct sftp_conn {
#define SFTP_EXT_HARDLINK 0x00000008
#define SFTP_EXT_FSYNC 0x00000010
#define SFTP_EXT_LSETSTAT 0x00000020
+#define SFTP_EXT_LIMITS 0x00000040
+#define SFTP_EXT_PATH_EXPAND 0x00000080
u_int exts;
u_int64_t limit_kbps;
struct bwlimit bwlimit_in, bwlimit_out;
};
+/* Tracks in-progress requests during file transfers */
+struct request {
+ u_int id;
+ size_t len;
+ u_int64_t offset;
+ TAILQ_ENTRY(request) tq;
+};
+TAILQ_HEAD(requests, request);
+
static u_char *
get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
const char *errfmt, ...) __attribute__((format(printf, 4, 5)));
+static struct request *
+request_enqueue(struct requests *requests, u_int id, size_t len,
+ uint64_t offset)
+{
+ struct request *req;
+
+ req = xcalloc(1, sizeof(*req));
+ req->id = id;
+ req->len = len;
+ req->offset = offset;
+ TAILQ_INSERT_TAIL(requests, req, tq);
+ return req;
+}
+
+static struct request *
+request_find(struct requests *requests, u_int id)
+{
+ struct request *req;
+
+ for (req = TAILQ_FIRST(requests);
+ req != NULL && req->id != id;
+ req = TAILQ_NEXT(req, tq))
+ ;
+ return req;
+}
+
/* ARGSUSED */
static int
sftpio(void *_bwlimit, size_t amount)
@@ -139,8 +190,9 @@ get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial)
u_char *p;
int r;
+ sshbuf_reset(m);
if ((r = sshbuf_reserve(m, 4, &p)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reserve");
if (atomicio6(read, conn->fd_in, p, 4, sftpio,
conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) {
if (errno == EPIPE || errno == ECONNRESET)
@@ -150,7 +202,7 @@ get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial)
}
if ((r = sshbuf_get_u32(m, &msg_len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_get_u32");
if (msg_len > SFTP_MAX_MSG_LENGTH) {
do_log2(initial ? SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_FATAL,
"Received message too long %u", msg_len);
@@ -159,7 +211,7 @@ get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial)
}
if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reserve");
if (atomicio6(read, conn->fd_in, p, msg_len, sftpio,
conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL)
!= msg_len) {
@@ -184,11 +236,11 @@ send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s,
int r;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, code)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_string(msg, s, len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
send_msg(conn, msg);
debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
sshbuf_free(msg);
@@ -202,14 +254,15 @@ send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code,
int r;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, code)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_string(msg, s, len)) != 0 ||
(r = encode_attrib(msg, a)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
send_msg(conn, msg);
- debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
+ debug3("Sent message fd %d T:%u I:%u F:0x%04x M:%05o",
+ conn->fd_out, code, id, a->flags, a->perm);
sshbuf_free(msg);
}
@@ -222,11 +275,11 @@ get_status(struct sftp_conn *conn, u_int expected_id)
int r;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
get_msg(conn, msg);
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
(r = sshbuf_get_u32(msg, &id)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
if (id != expected_id)
fatal("ID mismatch (%u != %u)", id, expected_id);
@@ -235,7 +288,7 @@ get_status(struct sftp_conn *conn, u_int expected_id)
SSH2_FXP_STATUS, type);
if ((r = sshbuf_get_u32(msg, &status)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
sshbuf_free(msg);
debug3("SSH2_FXP_STATUS %u", status);
@@ -261,18 +314,18 @@ get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
va_end(args);
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
get_msg(conn, msg);
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
(r = sshbuf_get_u32(msg, &id)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (id != expected_id)
fatal("%s: ID mismatch (%u != %u)",
errfmt == NULL ? __func__ : errmsg, id, expected_id);
if (type == SSH2_FXP_STATUS) {
if ((r = sshbuf_get_u32(msg, &status)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse status");
if (errfmt != NULL)
error("%s: %s", errmsg, fx2txt(status));
sshbuf_free(msg);
@@ -282,12 +335,13 @@ get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type);
if ((r = sshbuf_get_string(msg, &handle, len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse handle");
sshbuf_free(msg);
return handle;
}
+/* XXX returing &static is error-prone. Refactor to fill *Attrib argument */
static Attrib *
get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet)
{
@@ -298,21 +352,20 @@ get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet)
static Attrib a;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
get_msg(conn, msg);
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
(r = sshbuf_get_u32(msg, &id)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
- debug3("Received stat reply T:%u I:%u", type, id);
if (id != expected_id)
fatal("ID mismatch (%u != %u)", id, expected_id);
if (type == SSH2_FXP_STATUS) {
u_int status;
if ((r = sshbuf_get_u32(msg, &status)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse status");
if (quiet)
debug("Couldn't stat remote file: %s", fx2txt(status));
else
@@ -324,10 +377,12 @@ get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet)
SSH2_FXP_ATTRS, type);
}
if ((r = decode_attrib(msg, &a)) != 0) {
- error("%s: couldn't decode attrib: %s", __func__, ssh_err(r));
+ error_fr(r, "decode_attrib");
sshbuf_free(msg);
return NULL;
}
+ debug3("Recevied stat reply T:%u I:%u F:0x%04x M:%05o",
+ type, id, a.flags, a.perm);
sshbuf_free(msg);
return &a;
@@ -344,12 +399,12 @@ get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
int r;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
get_msg(conn, msg);
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
(r = sshbuf_get_u32(msg, &id)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug3("Received statvfs reply T:%u I:%u", type, id);
if (id != expected_id)
@@ -358,7 +413,7 @@ get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
u_int status;
if ((r = sshbuf_get_u32(msg, &status)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse status");
if (quiet)
debug("Couldn't statvfs: %s", fx2txt(status));
else
@@ -382,7 +437,7 @@ get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
(r = sshbuf_get_u64(msg, &st->f_fsid)) != 0 ||
(r = sshbuf_get_u64(msg, &flag)) != 0 ||
(r = sshbuf_get_u64(msg, &st->f_namemax)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse statvfs");
st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0;
st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0;
@@ -405,25 +460,26 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
ret->msg_id = 1;
ret->fd_in = fd_in;
ret->fd_out = fd_out;
- ret->transfer_buflen = transfer_buflen;
- ret->num_requests = num_requests;
+ ret->download_buflen = ret->upload_buflen =
+ transfer_buflen ? transfer_buflen : DEFAULT_COPY_BUFLEN;
+ ret->num_requests =
+ num_requests ? num_requests : DEFAULT_NUM_REQUESTS;
ret->exts = 0;
ret->limit_kbps = 0;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, SSH2_FXP_INIT)) != 0 ||
(r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- send_msg(ret, msg);
+ fatal_fr(r, "parse");
- sshbuf_reset(msg);
+ send_msg(ret, msg);
get_msg_extended(ret, msg, 1);
/* Expecting a VERSION reply */
if ((r = sshbuf_get_u8(msg, &type)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse type");
if (type != SSH2_FXP_VERSION) {
error("Invalid packet back from SSH2_FXP_INIT (type %u)",
type);
@@ -432,7 +488,7 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
return(NULL);
}
if ((r = sshbuf_get_u32(msg, &ret->version)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse version");
debug2("Remote version: %u", ret->version);
@@ -445,7 +501,7 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 ||
(r = sshbuf_get_string(msg, &value, &vlen)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse extension");
if (strcmp(name, "posix-rename@openssh.com") == 0 &&
strcmp((char *)value, "1") == 0) {
ret->exts |= SFTP_EXT_POSIX_RENAME;
@@ -470,6 +526,14 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
strcmp((char *)value, "1") == 0) {
ret->exts |= SFTP_EXT_LSETSTAT;
known = 1;
+ } else if (strcmp(name, "limits@openssh.com") == 0 &&
+ strcmp((char *)value, "1") == 0) {
+ ret->exts |= SFTP_EXT_LIMITS;
+ known = 1;
+ } else if (strcmp(name, "expand-path@openssh.com") == 0 &&
+ strcmp((char *)value, "1") == 0) {
+ ret->exts |= SFTP_EXT_PATH_EXPAND;
+ known = 1;
}
if (known) {
debug2("Server supports extension \"%s\" revision %s",
@@ -483,16 +547,42 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
sshbuf_free(msg);
+ /* Query the server for its limits */
+ if (ret->exts & SFTP_EXT_LIMITS) {
+ struct sftp_limits limits;
+ if (do_limits(ret, &limits) != 0)
+ fatal_f("limits failed");
+
+ /* If the caller did not specify, find a good value */
+ if (transfer_buflen == 0) {
+ ret->download_buflen = limits.read_length;
+ ret->upload_buflen = limits.write_length;
+ debug("Using server download size %u", ret->download_buflen);
+ debug("Using server upload size %u", ret->upload_buflen);
+ }
+
+ /* Use the server limit to scale down our value only */
+ if (num_requests == 0 && limits.open_handles) {
+ ret->num_requests =
+ MINIMUM(DEFAULT_NUM_REQUESTS, limits.open_handles);
+ debug("Server handle limit %llu; using %u",
+ (unsigned long long)limits.open_handles,
+ ret->num_requests);
+ }
+ }
+
/* Some filexfer v.0 servers don't support large packets */
- if (ret->version == 0)
- ret->transfer_buflen = MINIMUM(ret->transfer_buflen, 20480);
+ if (ret->version == 0) {
+ ret->download_buflen = MINIMUM(ret->download_buflen, 20480);
+ ret->upload_buflen = MINIMUM(ret->upload_buflen, 20480);
+ }
ret->limit_kbps = limit_kbps;
if (ret->limit_kbps > 0) {
bandwidth_limit_init(&ret->bwlimit_in, ret->limit_kbps,
- ret->transfer_buflen);
+ ret->download_buflen);
bandwidth_limit_init(&ret->bwlimit_out, ret->limit_kbps,
- ret->transfer_buflen);
+ ret->upload_buflen);
}
return ret;
@@ -505,6 +595,60 @@ sftp_proto_version(struct sftp_conn *conn)
}
int
+do_limits(struct sftp_conn *conn, struct sftp_limits *limits)
+{
+ u_int id, msg_id;
+ u_char type;
+ struct sshbuf *msg;
+ int r;
+
+ if ((conn->exts & SFTP_EXT_LIMITS) == 0) {
+ error("Server does not support limits@openssh.com extension");
+ return -1;
+ }
+
+ if ((msg = sshbuf_new()) == NULL)
+ fatal_f("sshbuf_new failed");
+
+ id = conn->msg_id++;
+ if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
+ (r = sshbuf_put_u32(msg, id)) != 0 ||
+ (r = sshbuf_put_cstring(msg, "limits@openssh.com")) != 0)
+ fatal_fr(r, "compose");
+ send_msg(conn, msg);
+ debug3("Sent message limits@openssh.com I:%u", id);
+
+ get_msg(conn, msg);
+
+ if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
+ (r = sshbuf_get_u32(msg, &msg_id)) != 0)
+ fatal_fr(r, "parse");
+
+ debug3("Received limits reply T:%u I:%u", type, msg_id);
+ if (id != msg_id)
+ fatal("ID mismatch (%u != %u)", msg_id, id);
+ if (type != SSH2_FXP_EXTENDED_REPLY) {
+ debug_f("expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
+ SSH2_FXP_EXTENDED_REPLY, type);
+ /* Disable the limits extension */
+ conn->exts &= ~SFTP_EXT_LIMITS;
+ sshbuf_free(msg);
+ return 0;
+ }
+
+ memset(limits, 0, sizeof(*limits));
+ if ((r = sshbuf_get_u64(msg, &limits->packet_length)) != 0 ||
+ (r = sshbuf_get_u64(msg, &limits->read_length)) != 0 ||
+ (r = sshbuf_get_u64(msg, &limits->write_length)) != 0 ||
+ (r = sshbuf_get_u64(msg, &limits->open_handles)) != 0)
+ fatal_fr(r, "parse limits");
+
+ sshbuf_free(msg);
+
+ return 0;
+}
+
+int
do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len)
{
u_int id, status;
@@ -512,13 +656,13 @@ do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len)
int r;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
id = conn->msg_id++;
if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_string(msg, handle, handle_len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
send_msg(conn, msg);
debug3("Sent message SSH2_FXP_CLOSE I:%u", id);
@@ -549,11 +693,11 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
id = conn->msg_id++;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, path)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose OPENDIR");
send_msg(conn, msg);
handle = get_handle(conn, id, &handle_len,
@@ -578,7 +722,7 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_string(msg, handle, handle_len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose READDIR");
send_msg(conn, msg);
sshbuf_reset(msg);
@@ -587,7 +731,7 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
(r = sshbuf_get_u32(msg, &id)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug3("Received reply T:%u I:%u", type, id);
@@ -598,8 +742,7 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
u_int rstatus;
if ((r = sshbuf_get_u32(msg, &rstatus)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "parse status");
debug3("Received SSH2_FXP_STATUS %d", rstatus);
if (rstatus == SSH2_FX_EOF)
break;
@@ -610,9 +753,9 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
SSH2_FXP_NAME, type);
if ((r = sshbuf_get_u32(msg, &count)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse count");
if (count > SSHBUF_SIZE_MAX)
- fatal("%s: nonsensical number of entries", __func__);
+ fatal_f("nonsensical number of entries");
if (count == 0)
break;
debug3("Received %d SSH2_FXP_NAME responses", count);
@@ -624,11 +767,9 @@ do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
NULL)) != 0 ||
(r = sshbuf_get_cstring(msg, &longname,
NULL)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "parse filenames");
if ((r = decode_attrib(msg, &a)) != 0) {
- error("%s: couldn't decode attrib: %s",
- __func__, ssh_err(r));
+ error_fr(r, "couldn't decode attrib");
free(filename);
free(longname);
goto out;
@@ -828,8 +969,9 @@ do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
return status == SSH2_FX_OK ? 0 : -1;
}
-char *
-do_realpath(struct sftp_conn *conn, const char *path)
+/* Implements both the realpath and expand-path operations */
+static char *
+do_realpath_expand(struct sftp_conn *conn, const char *path, int expand)
{
struct sshbuf *msg;
u_int expected_id, count, id;
@@ -837,18 +979,30 @@ do_realpath(struct sftp_conn *conn, const char *path)
Attrib a;
u_char type;
int r;
+ const char *what = "SSH2_FXP_REALPATH";
- expected_id = id = conn->msg_id++;
- send_string_request(conn, id, SSH2_FXP_REALPATH, path,
- strlen(path));
-
+ if (expand)
+ what = "expand-path@openssh.com";
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
+ expected_id = id = conn->msg_id++;
+ if (expand) {
+ if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
+ (r = sshbuf_put_u32(msg, id)) != 0 ||
+ (r = sshbuf_put_cstring(msg,
+ "expand-path@openssh.com")) != 0 ||
+ (r = sshbuf_put_cstring(msg, path)) != 0)
+ fatal_fr(r, "compose %s", what);
+ send_msg(conn, msg);
+ } else {
+ send_string_request(conn, id, SSH2_FXP_REALPATH,
+ path, strlen(path));
+ }
get_msg(conn, msg);
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
(r = sshbuf_get_u32(msg, &id)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (id != expected_id)
fatal("ID mismatch (%u != %u)", id, expected_id);
@@ -857,7 +1011,7 @@ do_realpath(struct sftp_conn *conn, const char *path)
u_int status;
if ((r = sshbuf_get_u32(msg, &status)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse status");
error("Couldn't canonicalize: %s", fx2txt(status));
sshbuf_free(msg);
return NULL;
@@ -866,17 +1020,16 @@ do_realpath(struct sftp_conn *conn, const char *path)
SSH2_FXP_NAME, type);
if ((r = sshbuf_get_u32(msg, &count)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse count");
if (count != 1)
- fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count);
+ fatal("Got multiple names (%d) from %s", count, what);
if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 ||
(r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 ||
(r = decode_attrib(msg, &a)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse filename/attrib");
- debug3("SSH_FXP_REALPATH %s -> %s size %lu", path, filename,
- (unsigned long)a.size);
+ debug3("%s %s -> %s", what, path, filename);
free(longname);
@@ -885,6 +1038,28 @@ do_realpath(struct sftp_conn *conn, const char *path)
return(filename);
}
+char *
+do_realpath(struct sftp_conn *conn, const char *path)
+{
+ return do_realpath_expand(conn, path, 0);
+}
+
+int
+can_expand_path(struct sftp_conn *conn)
+{
+ return (conn->exts & SFTP_EXT_PATH_EXPAND) != 0;
+}
+
+char *
+do_expand_path(struct sftp_conn *conn, const char *path)
+{
+ if (!can_expand_path(conn)) {
+ debug3_f("no server support, fallback to realpath");
+ return do_realpath_expand(conn, path, 0);
+ }
+ return do_realpath_expand(conn, path, 1);
+}
+
int
do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath,
int force_legacy)
@@ -894,7 +1069,7 @@ do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath,
int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
/* Send rename request */
id = conn->msg_id++;
@@ -903,15 +1078,15 @@ do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath,
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg,
"posix-rename@openssh.com")) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose posix-rename");
} else {
if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose rename");
}
if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
(r = sshbuf_put_cstring(msg, newpath)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose paths");
send_msg(conn, msg);
debug3("Sent message %s \"%s\" -> \"%s\"",
use_ext ? "posix-rename@openssh.com" :
@@ -939,7 +1114,7 @@ do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
}
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
/* Send link request */
id = conn->msg_id++;
@@ -948,10 +1123,10 @@ do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
(r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 ||
(r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
(r = sshbuf_put_cstring(msg, newpath)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
send_msg(conn, msg);
debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"",
- oldpath, newpath);
+ oldpath, newpath);
sshbuf_free(msg);
status = get_status(conn, id);
@@ -975,7 +1150,7 @@ do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
}
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
/* Send symlink request */
id = conn->msg_id++;
@@ -983,7 +1158,7 @@ do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
(r = sshbuf_put_cstring(msg, newpath)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
send_msg(conn, msg);
debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
newpath);
@@ -1010,13 +1185,13 @@ do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len)
/* Send fsync request */
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
id = conn->msg_id++;
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 ||
(r = sshbuf_put_string(msg, handle, handle_len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
send_msg(conn, msg);
debug3("Sent message fsync@openssh.com I:%u", id);
sshbuf_free(msg);
@@ -1043,12 +1218,12 @@ do_readlink(struct sftp_conn *conn, const char *path)
send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path));
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
get_msg(conn, msg);
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
(r = sshbuf_get_u32(msg, &id)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (id != expected_id)
fatal("ID mismatch (%u != %u)", id, expected_id);
@@ -1057,7 +1232,7 @@ do_readlink(struct sftp_conn *conn, const char *path)
u_int status;
if ((r = sshbuf_get_u32(msg, &status)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse status");
error("Couldn't readlink: %s", fx2txt(status));
sshbuf_free(msg);
return(NULL);
@@ -1066,14 +1241,14 @@ do_readlink(struct sftp_conn *conn, const char *path)
SSH2_FXP_NAME, type);
if ((r = sshbuf_get_u32(msg, &count)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse count");
if (count != 1)
fatal("Got multiple names (%d) from SSH_FXP_READLINK", count);
if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 ||
(r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 ||
(r = decode_attrib(msg, &a)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse filenames/attrib");
debug3("SSH_FXP_READLINK %s -> %s", path, filename);
@@ -1101,12 +1276,12 @@ do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
id = conn->msg_id++;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 ||
(r = sshbuf_put_cstring(msg, path)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
send_msg(conn, msg);
sshbuf_free(msg);
@@ -1129,12 +1304,12 @@ do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
id = conn->msg_id++;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 ||
(r = sshbuf_put_string(msg, handle, handle_len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
send_msg(conn, msg);
sshbuf_free(msg);
@@ -1156,13 +1331,13 @@ do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a)
id = conn->msg_id++;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 ||
(r = sshbuf_put_cstring(msg, path)) != 0 ||
(r = encode_attrib(msg, a)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
send_msg(conn, msg);
sshbuf_free(msg);
@@ -1182,23 +1357,76 @@ send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset,
int r;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_string(msg, handle, handle_len)) != 0 ||
(r = sshbuf_put_u64(msg, offset)) != 0 ||
(r = sshbuf_put_u32(msg, len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
send_msg(conn, msg);
sshbuf_free(msg);
}
+static int
+send_open(struct sftp_conn *conn, const char *path, const char *tag,
+ u_int openmode, Attrib *a, u_char **handlep, size_t *handle_lenp)
+{
+ Attrib junk;
+ u_char *handle;
+ size_t handle_len;
+ struct sshbuf *msg;
+ int r;
+ u_int id;
+
+ *handlep = NULL;
+ *handle_lenp = 0;
+
+ if (a == NULL) {
+ attrib_clear(&junk); /* Send empty attributes */
+ a = &junk;
+ }
+ /* Send open request */
+ if ((msg = sshbuf_new()) == NULL)
+ fatal_f("sshbuf_new failed");
+ id = conn->msg_id++;
+ if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
+ (r = sshbuf_put_u32(msg, id)) != 0 ||
+ (r = sshbuf_put_cstring(msg, path)) != 0 ||
+ (r = sshbuf_put_u32(msg, openmode)) != 0 ||
+ (r = encode_attrib(msg, a)) != 0)
+ fatal_fr(r, "compose %s open", tag);
+ send_msg(conn, msg);
+ sshbuf_free(msg);
+ debug3("Sent %s message SSH2_FXP_OPEN I:%u P:%s M:0x%04x",
+ tag, id, path, openmode);
+ if ((handle = get_handle(conn, id, &handle_len,
+ "%s open(\"%s\")", tag, path)) == NULL)
+ return -1;
+ /* success */
+ *handlep = handle;
+ *handle_lenp = handle_len;
+ return 0;
+}
+
+static const char *
+progress_meter_path(const char *path)
+{
+ const char *progresspath;
+
+ if ((progresspath = strrchr(path, '/')) == NULL)
+ return path;
+ progresspath++;
+ if (*progresspath == '\0')
+ return path;
+ return progresspath;
+}
+
int
do_download(struct sftp_conn *conn, const char *remote_path,
const char *local_path, Attrib *a, int preserve_flag, int resume_flag,
int fsync_flag)
{
- Attrib junk;
struct sshbuf *msg;
u_char *handle;
int local_fd = -1, write_error;
@@ -1208,13 +1436,7 @@ do_download(struct sftp_conn *conn, const char *remote_path,
off_t progress_counter;
size_t handle_len;
struct stat st;
- struct request {
- u_int id;
- size_t len;
- u_int64_t offset;
- TAILQ_ENTRY(request) tq;
- };
- TAILQ_HEAD(reqhead, request) requests;
+ struct requests requests;
struct request *req;
u_char type;
@@ -1240,29 +1462,12 @@ do_download(struct sftp_conn *conn, const char *remote_path,
else
size = 0;
- buflen = conn->transfer_buflen;
- if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
-
- attrib_clear(&junk); /* Send empty attributes */
+ buflen = conn->download_buflen;
/* Send open request */
- id = conn->msg_id++;
- if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
- (r = sshbuf_put_u32(msg, id)) != 0 ||
- (r = sshbuf_put_cstring(msg, remote_path)) != 0 ||
- (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 ||
- (r = encode_attrib(msg, &junk)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- send_msg(conn, msg);
- debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
-
- handle = get_handle(conn, id, &handle_len,
- "remote open(\"%s\")", remote_path);
- if (handle == NULL) {
- sshbuf_free(msg);
- return(-1);
- }
+ if (send_open(conn, remote_path, "remote", SSH2_FXF_READ, NULL,
+ &handle, &handle_len) != 0)
+ return -1;
local_fd = open(local_path,
O_WRONLY | O_CREAT | (resume_flag ? 0 : O_TRUNC), mode | S_IWUSR);
@@ -1287,7 +1492,6 @@ do_download(struct sftp_conn *conn, const char *remote_path,
"local file is larger than remote", local_path);
fail:
do_close(conn, handle, handle_len);
- sshbuf_free(msg);
free(handle);
if (local_fd != -1)
close(local_fd);
@@ -1301,8 +1505,13 @@ do_download(struct sftp_conn *conn, const char *remote_path,
max_req = 1;
progress_counter = offset;
- if (showprogress && size != 0)
- start_progress_meter(remote_path, size, &progress_counter);
+ if (showprogress && size != 0) {
+ start_progress_meter(progress_meter_path(remote_path),
+ size, &progress_counter);
+ }
+
+ if ((msg = sshbuf_new()) == NULL)
+ fatal_f("sshbuf_new failed");
while (num_req > 0 || max_req > 0) {
u_char *data;
@@ -1324,13 +1533,10 @@ do_download(struct sftp_conn *conn, const char *remote_path,
(unsigned long long)offset,
(unsigned long long)offset + buflen - 1,
num_req, max_req);
- req = xcalloc(1, sizeof(*req));
- req->id = conn->msg_id++;
- req->len = buflen;
- req->offset = offset;
+ req = request_enqueue(&requests, conn->msg_id++,
+ buflen, offset);
offset += buflen;
num_req++;
- TAILQ_INSERT_TAIL(&requests, req, tq);
send_read_request(conn, req->id, req->offset,
req->len, handle, handle_len);
}
@@ -1339,22 +1545,17 @@ do_download(struct sftp_conn *conn, const char *remote_path,
get_msg(conn, msg);
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
(r = sshbuf_get_u32(msg, &id)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug3("Received reply T:%u I:%u R:%d", type, id, max_req);
/* Find the request in our queue */
- for (req = TAILQ_FIRST(&requests);
- req != NULL && req->id != id;
- req = TAILQ_NEXT(req, tq))
- ;
- if (req == NULL)
+ if ((req = request_find(&requests, id)) == NULL)
fatal("Unexpected reply %u", id);
switch (type) {
case SSH2_FXP_STATUS:
if ((r = sshbuf_get_u32(msg, &status)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "parse status");
if (status != SSH2_FX_EOF)
read_error = 1;
max_req = 0;
@@ -1364,8 +1565,7 @@ do_download(struct sftp_conn *conn, const char *remote_path,
break;
case SSH2_FXP_DATA:
if ((r = sshbuf_get_string(msg, &data, &len)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "parse data");
debug3("Received data %llu -> %llu",
(unsigned long long)req->offset,
(unsigned long long)req->offset + len - 1);
@@ -1415,7 +1615,7 @@ do_download(struct sftp_conn *conn, const char *remote_path,
(unsigned long long)offset,
num_req);
max_req = 1;
- } else if (max_req <= conn->num_requests) {
+ } else if (max_req < conn->num_requests) {
++max_req;
}
}
@@ -1495,12 +1695,12 @@ do_download(struct sftp_conn *conn, const char *remote_path,
static int
download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
int depth, Attrib *dirattrib, int preserve_flag, int print_flag,
- int resume_flag, int fsync_flag)
+ int resume_flag, int fsync_flag, int follow_link_flag)
{
int i, ret = 0;
SFTP_DIRENT **dir_entries;
char *filename, *new_src = NULL, *new_dst = NULL;
- mode_t mode = 0777;
+ mode_t mode = 0777, tmpmode = mode;
if (depth >= MAX_DIR_DEPTH) {
error("Maximum directory depth exceeded: %d levels", depth);
@@ -1516,17 +1716,18 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
error("\"%s\" is not a directory", src);
return -1;
}
- if (print_flag)
+ if (print_flag && print_flag != SFTP_PROGRESS_ONLY)
mprintf("Retrieving %s\n", src);
- if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
+ if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
mode = dirattrib->perm & 01777;
- else {
+ tmpmode = mode | (S_IWUSR|S_IXUSR);
+ } else {
debug("Server did not send permissions for "
"directory \"%s\"", dst);
}
- if (mkdir(dst, mode) == -1 && errno != EEXIST) {
+ if (mkdir(dst, tmpmode) == -1 && errno != EEXIST) {
error("mkdir %s: %s", dst, strerror(errno));
return -1;
}
@@ -1550,12 +1751,20 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
continue;
if (download_dir_internal(conn, new_src, new_dst,
depth + 1, &(dir_entries[i]->a), preserve_flag,
- print_flag, resume_flag, fsync_flag) == -1)
+ print_flag, resume_flag,
+ fsync_flag, follow_link_flag) == -1)
ret = -1;
- } else if (S_ISREG(dir_entries[i]->a.perm) ) {
+ } else if (S_ISREG(dir_entries[i]->a.perm) ||
+ (follow_link_flag && S_ISLNK(dir_entries[i]->a.perm))) {
+ /*
+ * If this is a symlink then don't send the link's
+ * Attrib. do_download() will do a FXP_STAT operation
+ * and get the link target's attributes.
+ */
if (do_download(conn, new_src, new_dst,
- &(dir_entries[i]->a), preserve_flag,
- resume_flag, fsync_flag) == -1) {
+ S_ISLNK(dir_entries[i]->a.perm) ? NULL :
+ &(dir_entries[i]->a),
+ preserve_flag, resume_flag, fsync_flag) == -1) {
error("Download of file %s to %s failed",
new_src, new_dst);
ret = -1;
@@ -1581,6 +1790,10 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
"\"%s\"", dst);
}
+ if (mode != tmpmode && chmod(dst, mode) == -1)
+ error("Can't set final mode on \"%s\": %s", dst,
+ strerror(errno));
+
free_sftp_dirents(dir_entries);
return ret;
@@ -1589,7 +1802,7 @@ download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
int
download_dir(struct sftp_conn *conn, const char *src, const char *dst,
Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag,
- int fsync_flag)
+ int fsync_flag, int follow_link_flag)
{
char *src_canon;
int ret;
@@ -1600,7 +1813,8 @@ download_dir(struct sftp_conn *conn, const char *src, const char *dst,
}
ret = download_dir_internal(conn, src_canon, dst, 0,
- dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag);
+ dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag,
+ follow_link_flag);
free(src_canon);
return ret;
}
@@ -1620,14 +1834,8 @@ do_upload(struct sftp_conn *conn, const char *local_path,
Attrib a, *c = NULL;
u_int32_t startid;
u_int32_t ackid;
- struct outstanding_ack {
- u_int id;
- u_int len;
- off_t offset;
- TAILQ_ENTRY(outstanding_ack) tq;
- };
- TAILQ_HEAD(ackhead, outstanding_ack) acks;
- struct outstanding_ack *ack = NULL;
+ struct request *ack = NULL;
+ struct requests acks;
size_t handle_len;
TAILQ_INIT(&acks);
@@ -1665,7 +1873,7 @@ do_upload(struct sftp_conn *conn, const char *local_path,
if ((off_t)c->size >= sb.st_size) {
error("destination file bigger or same size as "
- "source file");
+ "source file");
close(local_fd);
return -1;
}
@@ -1676,40 +1884,27 @@ do_upload(struct sftp_conn *conn, const char *local_path,
}
}
- if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
-
/* Send open request */
- id = conn->msg_id++;
- if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
- (r = sshbuf_put_u32(msg, id)) != 0 ||
- (r = sshbuf_put_cstring(msg, remote_path)) != 0 ||
- (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|
- (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC))) != 0 ||
- (r = encode_attrib(msg, &a)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- send_msg(conn, msg);
- debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
-
- sshbuf_reset(msg);
-
- handle = get_handle(conn, id, &handle_len,
- "remote open(\"%s\")", remote_path);
- if (handle == NULL) {
+ if (send_open(conn, remote_path, "dest", SSH2_FXF_WRITE|SSH2_FXF_CREAT|
+ (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC),
+ &a, &handle, &handle_len) != 0) {
close(local_fd);
- sshbuf_free(msg);
return -1;
}
+ id = conn->msg_id;
startid = ackid = id + 1;
- data = xmalloc(conn->transfer_buflen);
+ data = xmalloc(conn->upload_buflen);
/* Read from local and write to remote */
offset = progress_counter = (resume ? c->size : 0);
- if (showprogress)
- start_progress_meter(local_path, sb.st_size,
- &progress_counter);
+ if (showprogress) {
+ start_progress_meter(progress_meter_path(local_path),
+ sb.st_size, &progress_counter);
+ }
+ if ((msg = sshbuf_new()) == NULL)
+ fatal_f("sshbuf_new failed");
for (;;) {
int len;
@@ -1722,7 +1917,7 @@ do_upload(struct sftp_conn *conn, const char *local_path,
if (interrupted || status != SSH2_FX_OK)
len = 0;
else do
- len = read(local_fd, data, conn->transfer_buflen);
+ len = read(local_fd, data, conn->upload_buflen);
while ((len == -1) &&
(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
@@ -1731,12 +1926,7 @@ do_upload(struct sftp_conn *conn, const char *local_path,
strerror(errno));
if (len != 0) {
- ack = xcalloc(1, sizeof(*ack));
- ack->id = ++id;
- ack->offset = offset;
- ack->len = len;
- TAILQ_INSERT_TAIL(&acks, ack, tq);
-
+ ack = request_enqueue(&acks, ++id, len, offset);
sshbuf_reset(msg);
if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 ||
(r = sshbuf_put_u32(msg, ack->id)) != 0 ||
@@ -1744,8 +1934,7 @@ do_upload(struct sftp_conn *conn, const char *local_path,
handle_len)) != 0 ||
(r = sshbuf_put_u64(msg, offset)) != 0 ||
(r = sshbuf_put_string(msg, data, len)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "compose");
send_msg(conn, msg);
debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u",
id, (unsigned long long)offset, len);
@@ -1763,35 +1952,29 @@ do_upload(struct sftp_conn *conn, const char *local_path,
get_msg(conn, msg);
if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
(r = sshbuf_get_u32(msg, &rid)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (type != SSH2_FXP_STATUS)
fatal("Expected SSH2_FXP_STATUS(%d) packet, "
"got %d", SSH2_FXP_STATUS, type);
if ((r = sshbuf_get_u32(msg, &status)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "parse status");
debug3("SSH2_FXP_STATUS %u", status);
/* Find the request in our queue */
- for (ack = TAILQ_FIRST(&acks);
- ack != NULL && ack->id != rid;
- ack = TAILQ_NEXT(ack, tq))
- ;
- if (ack == NULL)
+ if ((ack = request_find(&acks, rid)) == NULL)
fatal("Can't find request for ID %u", rid);
TAILQ_REMOVE(&acks, ack, tq);
- debug3("In write loop, ack for %u %u bytes at %lld",
- ack->id, ack->len, (long long)ack->offset);
+ debug3("In write loop, ack for %u %zu bytes at %lld",
+ ack->id, ack->len, (unsigned long long)ack->offset);
++ackid;
progress_counter += ack->len;
free(ack);
}
offset += len;
if (offset < 0)
- fatal("%s: offset < 0", __func__);
+ fatal_f("offset < 0");
}
sshbuf_free(msg);
@@ -1828,7 +2011,8 @@ do_upload(struct sftp_conn *conn, const char *local_path,
static int
upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
- int depth, int preserve_flag, int print_flag, int resume, int fsync_flag)
+ int depth, int preserve_flag, int print_flag, int resume, int fsync_flag,
+ int follow_link_flag)
{
int ret = 0;
DIR *dirp;
@@ -1836,6 +2020,7 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
char *filename, *new_src = NULL, *new_dst = NULL;
struct stat sb;
Attrib a, *dirattrib;
+ u_int32_t saved_perm;
if (depth >= MAX_DIR_DEPTH) {
error("Maximum directory depth exceeded: %d levels", depth);
@@ -1851,10 +2036,9 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
error("\"%s\" is not a directory", src);
return -1;
}
- if (print_flag)
+ if (print_flag && print_flag != SFTP_PROGRESS_ONLY)
mprintf("Entering %s\n", src);
- attrib_clear(&a);
stat_to_attrib(&sb, &a);
a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
@@ -1865,8 +2049,11 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
/*
* sftp lacks a portable status value to match errno EEXIST,
* so if we get a failure back then we must check whether
- * the path already existed and is a directory.
+ * the path already existed and is a directory. Ensure we can
+ * write to the directory we create for the duration of the transfer.
*/
+ saved_perm = a.perm;
+ a.perm |= (S_IWUSR|S_IXUSR);
if (do_mkdir(conn, dst, &a, 0) != 0) {
if ((dirattrib = do_stat(conn, dst, 0)) == NULL)
return -1;
@@ -1875,6 +2062,7 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
return -1;
}
}
+ a.perm = saved_perm;
if ((dirp = opendir(src)) == NULL) {
error("Failed to open dir \"%s\": %s", src, strerror(errno));
@@ -1901,9 +2089,10 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
if (upload_dir_internal(conn, new_src, new_dst,
depth + 1, preserve_flag, print_flag, resume,
- fsync_flag) == -1)
+ fsync_flag, follow_link_flag) == -1)
ret = -1;
- } else if (S_ISREG(sb.st_mode)) {
+ } else if (S_ISREG(sb.st_mode) ||
+ (follow_link_flag && S_ISLNK(sb.st_mode))) {
if (do_upload(conn, new_src, new_dst,
preserve_flag, resume, fsync_flag) == -1) {
error("Uploading of file %s to %s failed!",
@@ -1924,7 +2113,8 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
int
upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
- int preserve_flag, int print_flag, int resume, int fsync_flag)
+ int preserve_flag, int print_flag, int resume, int fsync_flag,
+ int follow_link_flag)
{
char *dst_canon;
int ret;
@@ -1935,12 +2125,448 @@ upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
}
ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag,
- print_flag, resume, fsync_flag);
+ print_flag, resume, fsync_flag, follow_link_flag);
free(dst_canon);
return ret;
}
+static void
+handle_dest_replies(struct sftp_conn *to, const char *to_path, int synchronous,
+ u_int *nreqsp, u_int *write_errorp)
+{
+ struct sshbuf *msg;
+ u_char type;
+ u_int id, status;
+ int r;
+ struct pollfd pfd;
+
+ if ((msg = sshbuf_new()) == NULL)
+ fatal_f("sshbuf_new failed");
+
+ /* Try to eat replies from the upload side */
+ while (*nreqsp > 0) {
+ debug3_f("%u outstanding replies", *nreqsp);
+ if (!synchronous) {
+ /* Bail out if no data is ready to be read */
+ pfd.fd = to->fd_in;
+ pfd.events = POLLIN;
+ if ((r = poll(&pfd, 1, 0)) == -1) {
+ if (errno == EINTR)
+ break;
+ fatal_f("poll: %s", strerror(errno));
+ } else if (r == 0)
+ break; /* fd not ready */
+ }
+ sshbuf_reset(msg);
+ get_msg(to, msg);
+
+ if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
+ (r = sshbuf_get_u32(msg, &id)) != 0)
+ fatal_fr(r, "dest parse");
+ debug3("Received dest reply T:%u I:%u R:%u", type, id, *nreqsp);
+ if (type != SSH2_FXP_STATUS) {
+ fatal_f("Expected SSH2_FXP_STATUS(%d) packet, got %d",
+ SSH2_FXP_STATUS, type);
+ }
+ if ((r = sshbuf_get_u32(msg, &status)) != 0)
+ fatal_fr(r, "parse dest status");
+ debug3("dest SSH2_FXP_STATUS %u", status);
+ if (status != SSH2_FX_OK) {
+ /* record first error */
+ if (*write_errorp == 0)
+ *write_errorp = status;
+ }
+ /*
+ * XXX this doesn't do full reply matching like do_upload and
+ * so cannot gracefully truncate terminated uploads at a
+ * high-water mark. ATM the only caller of this function (scp)
+ * doesn't support transfer resumption, so this doesn't matter
+ * a whole lot.
+ *
+ * To be safe, do_crossload truncates the destination file to
+ * zero length on upload failure, since we can't trust the
+ * server not to have reordered replies that could have
+ * inserted holes where none existed in the source file.
+ *
+ * XXX we could get a more accutate progress bar if we updated
+ * the counter based on the reply from the destination...
+ */
+ (*nreqsp)--;
+ }
+ debug3_f("done: %u outstanding replies", *nreqsp);
+}
+
+int
+do_crossload(struct sftp_conn *from, struct sftp_conn *to,
+ const char *from_path, const char *to_path,
+ Attrib *a, int preserve_flag)
+{
+ struct sshbuf *msg;
+ int write_error, read_error, r;
+ u_int64_t offset = 0, size;
+ u_int id, buflen, num_req, max_req, status = SSH2_FX_OK;
+ u_int num_upload_req;
+ off_t progress_counter;
+ u_char *from_handle, *to_handle;
+ size_t from_handle_len, to_handle_len;
+ struct requests requests;
+ struct request *req;
+ u_char type;
+
+ TAILQ_INIT(&requests);
+
+ if (a == NULL && (a = do_stat(from, from_path, 0)) == NULL)
+ return -1;
+
+ if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
+ (!S_ISREG(a->perm))) {
+ error("Cannot download non-regular file: %s", from_path);
+ return(-1);
+ }
+ if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
+ size = a->size;
+ else
+ size = 0;
+
+ buflen = from->download_buflen;
+ if (buflen > to->upload_buflen)
+ buflen = to->upload_buflen;
+
+ /* Send open request to read side */
+ if (send_open(from, from_path, "origin", SSH2_FXF_READ, NULL,
+ &from_handle, &from_handle_len) != 0)
+ return -1;
+
+ /* Send open request to write side */
+ a->flags &= ~SSH2_FILEXFER_ATTR_SIZE;
+ a->flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
+ a->perm &= 0777;
+ if (!preserve_flag)
+ a->flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
+ if (send_open(to, to_path, "dest",
+ SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a,
+ &to_handle, &to_handle_len) != 0) {
+ do_close(from, from_handle, from_handle_len);
+ return -1;
+ }
+
+ /* Read from remote "from" and write to remote "to" */
+ offset = 0;
+ write_error = read_error = num_req = num_upload_req = 0;
+ max_req = 1;
+ progress_counter = 0;
+
+ if (showprogress && size != 0) {
+ start_progress_meter(progress_meter_path(from_path),
+ size, &progress_counter);
+ }
+ if ((msg = sshbuf_new()) == NULL)
+ fatal_f("sshbuf_new failed");
+ while (num_req > 0 || max_req > 0) {
+ u_char *data;
+ size_t len;
+
+ /*
+ * Simulate EOF on interrupt: stop sending new requests and
+ * allow outstanding requests to drain gracefully
+ */
+ if (interrupted) {
+ if (num_req == 0) /* If we haven't started yet... */
+ break;
+ max_req = 0;
+ }
+
+ /* Send some more requests */
+ while (num_req < max_req) {
+ debug3("Request range %llu -> %llu (%d/%d)",
+ (unsigned long long)offset,
+ (unsigned long long)offset + buflen - 1,
+ num_req, max_req);
+ req = request_enqueue(&requests, from->msg_id++,
+ buflen, offset);
+ offset += buflen;
+ num_req++;
+ send_read_request(from, req->id, req->offset,
+ req->len, from_handle, from_handle_len);
+ }
+
+ /* Try to eat replies from the upload side (nonblocking) */
+ handle_dest_replies(to, to_path, 0,
+ &num_upload_req, &write_error);
+
+ sshbuf_reset(msg);
+ get_msg(from, msg);
+ if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
+ (r = sshbuf_get_u32(msg, &id)) != 0)
+ fatal_fr(r, "parse");
+ debug3("Received origin reply T:%u I:%u R:%d",
+ type, id, max_req);
+
+ /* Find the request in our queue */
+ if ((req = request_find(&requests, id)) == NULL)
+ fatal("Unexpected reply %u", id);
+
+ switch (type) {
+ case SSH2_FXP_STATUS:
+ if ((r = sshbuf_get_u32(msg, &status)) != 0)
+ fatal_fr(r, "parse status");
+ if (status != SSH2_FX_EOF)
+ read_error = 1;
+ max_req = 0;
+ TAILQ_REMOVE(&requests, req, tq);
+ free(req);
+ num_req--;
+ break;
+ case SSH2_FXP_DATA:
+ if ((r = sshbuf_get_string(msg, &data, &len)) != 0)
+ fatal_fr(r, "parse data");
+ debug3("Received data %llu -> %llu",
+ (unsigned long long)req->offset,
+ (unsigned long long)req->offset + len - 1);
+ if (len > req->len)
+ fatal("Received more data than asked for "
+ "%zu > %zu", len, req->len);
+
+ /* Write this chunk out to the destination */
+ sshbuf_reset(msg);
+ if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 ||
+ (r = sshbuf_put_u32(msg, to->msg_id++)) != 0 ||
+ (r = sshbuf_put_string(msg, to_handle,
+ to_handle_len)) != 0 ||
+ (r = sshbuf_put_u64(msg, req->offset)) != 0 ||
+ (r = sshbuf_put_string(msg, data, len)) != 0)
+ fatal_fr(r, "compose write");
+ send_msg(to, msg);
+ debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%zu",
+ id, (unsigned long long)offset, len);
+ num_upload_req++;
+ progress_counter += len;
+ free(data);
+
+ if (len == req->len) {
+ TAILQ_REMOVE(&requests, req, tq);
+ free(req);
+ num_req--;
+ } else {
+ /* Resend the request for the missing data */
+ debug3("Short data block, re-requesting "
+ "%llu -> %llu (%2d)",
+ (unsigned long long)req->offset + len,
+ (unsigned long long)req->offset +
+ req->len - 1, num_req);
+ req->id = from->msg_id++;
+ req->len -= len;
+ req->offset += len;
+ send_read_request(from, req->id,
+ req->offset, req->len,
+ from_handle, from_handle_len);
+ /* Reduce the request size */
+ if (len < buflen)
+ buflen = MAXIMUM(MIN_READ_SIZE, len);
+ }
+ if (max_req > 0) { /* max_req = 0 iff EOF received */
+ if (size > 0 && offset > size) {
+ /* Only one request at a time
+ * after the expected EOF */
+ debug3("Finish at %llu (%2d)",
+ (unsigned long long)offset,
+ num_req);
+ max_req = 1;
+ } else if (max_req < from->num_requests) {
+ ++max_req;
+ }
+ }
+ break;
+ default:
+ fatal("Expected SSH2_FXP_DATA(%u) packet, got %u",
+ SSH2_FXP_DATA, type);
+ }
+ }
+
+ if (showprogress && size)
+ stop_progress_meter();
+
+ /* Drain replies from the server (blocking) */
+ debug3_f("waiting for %u replies from destination", num_upload_req);
+ handle_dest_replies(to, to_path, 1, &num_upload_req, &write_error);
+
+ /* Sanity check */
+ if (TAILQ_FIRST(&requests) != NULL)
+ fatal("Transfer complete, but requests still in queue");
+ /* Truncate at 0 length on interrupt or error to avoid holes at dest */
+ if (read_error || write_error || interrupted) {
+ debug("truncating \"%s\" at 0", to_path);
+ do_close(to, to_handle, to_handle_len);
+ free(to_handle);
+ if (send_open(to, to_path, "dest",
+ SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a,
+ &to_handle, &to_handle_len) != 0) {
+ error("truncation failed for \"%s\"", to_path);
+ to_handle = NULL;
+ }
+ }
+ if (read_error) {
+ error("Couldn't read from origin file \"%s\" : %s",
+ from_path, fx2txt(status));
+ status = -1;
+ do_close(from, from_handle, from_handle_len);
+ if (to_handle != NULL)
+ do_close(to, to_handle, to_handle_len);
+ } else if (write_error) {
+ error("Couldn't write to \"%s\": %s",
+ to_path, fx2txt(write_error));
+ status = SSH2_FX_FAILURE;
+ do_close(from, from_handle, from_handle_len);
+ if (to_handle != NULL)
+ do_close(to, to_handle, to_handle_len);
+ } else {
+ if (do_close(from, from_handle, from_handle_len) != 0 ||
+ interrupted)
+ status = -1;
+ else
+ status = SSH2_FX_OK;
+ if (to_handle != NULL) {
+ /* Need to resend utimes after write */
+ if (preserve_flag)
+ do_fsetstat(to, to_handle, to_handle_len, a);
+ do_close(to, to_handle, to_handle_len);
+ }
+ }
+ sshbuf_free(msg);
+ free(from_handle);
+ free(to_handle);
+
+ return status == SSH2_FX_OK ? 0 : -1;
+}
+
+static int
+crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to,
+ const char *from_path, const char *to_path,
+ int depth, Attrib *dirattrib, int preserve_flag, int print_flag,
+ int follow_link_flag)
+{
+ int i, ret = 0;
+ SFTP_DIRENT **dir_entries;
+ char *filename, *new_from_path = NULL, *new_to_path = NULL;
+ mode_t mode = 0777;
+ Attrib curdir;
+
+ if (depth >= MAX_DIR_DEPTH) {
+ error("Maximum directory depth exceeded: %d levels", depth);
+ return -1;
+ }
+
+ if (dirattrib == NULL &&
+ (dirattrib = do_stat(from, from_path, 1)) == NULL) {
+ error("Unable to stat remote directory \"%s\"", from_path);
+ return -1;
+ }
+ if (!S_ISDIR(dirattrib->perm)) {
+ error("\"%s\" is not a directory", from_path);
+ return -1;
+ }
+ if (print_flag && print_flag != SFTP_PROGRESS_ONLY)
+ mprintf("Retrieving %s\n", from_path);
+
+ curdir = *dirattrib; /* dirattrib will be clobbered */
+ curdir.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
+ curdir.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
+ if ((curdir.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) == 0) {
+ debug("Origin did not send permissions for "
+ "directory \"%s\"", to_path);
+ curdir.perm = S_IWUSR|S_IXUSR;
+ curdir.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
+ }
+ /* We need to be able to write to the directory while we transfer it */
+ mode = curdir.perm & 01777;
+ curdir.perm = mode | (S_IWUSR|S_IXUSR);
+
+ /*
+ * sftp lacks a portable status value to match errno EEXIST,
+ * so if we get a failure back then we must check whether
+ * the path already existed and is a directory. Ensure we can
+ * write to the directory we create for the duration of the transfer.
+ */
+ if (do_mkdir(to, to_path, &curdir, 0) != 0) {
+ if ((dirattrib = do_stat(to, to_path, 0)) == NULL)
+ return -1;
+ if (!S_ISDIR(dirattrib->perm)) {
+ error("\"%s\" exists but is not a directory", to_path);
+ return -1;
+ }
+ }
+ curdir.perm = mode;
+
+ if (do_readdir(from, from_path, &dir_entries) == -1) {
+ error("%s: Failed to get directory contents", from_path);
+ return -1;
+ }
+
+ for (i = 0; dir_entries[i] != NULL && !interrupted; i++) {
+ free(new_from_path);
+ free(new_to_path);
+
+ filename = dir_entries[i]->filename;
+ new_from_path = path_append(from_path, filename);
+ new_to_path = path_append(to_path, filename);
+
+ if (S_ISDIR(dir_entries[i]->a.perm)) {
+ if (strcmp(filename, ".") == 0 ||
+ strcmp(filename, "..") == 0)
+ continue;
+ if (crossload_dir_internal(from, to,
+ new_from_path, new_to_path,
+ depth + 1, &(dir_entries[i]->a), preserve_flag,
+ print_flag, follow_link_flag) == -1)
+ ret = -1;
+ } else if (S_ISREG(dir_entries[i]->a.perm) ||
+ (follow_link_flag && S_ISLNK(dir_entries[i]->a.perm))) {
+ /*
+ * If this is a symlink then don't send the link's
+ * Attrib. do_download() will do a FXP_STAT operation
+ * and get the link target's attributes.
+ */
+ if (do_crossload(from, to, new_from_path, new_to_path,
+ S_ISLNK(dir_entries[i]->a.perm) ? NULL :
+ &(dir_entries[i]->a), preserve_flag) == -1) {
+ error("Transfer of file %s to %s failed",
+ new_from_path, new_to_path);
+ ret = -1;
+ }
+ } else
+ logit("%s: not a regular file\n", new_from_path);
+
+ }
+ free(new_to_path);
+ free(new_from_path);
+
+ do_setstat(to, to_path, &curdir);
+
+ free_sftp_dirents(dir_entries);
+
+ return ret;
+}
+
+int
+crossload_dir(struct sftp_conn *from, struct sftp_conn *to,
+ const char *from_path, const char *to_path,
+ Attrib *dirattrib, int preserve_flag, int print_flag, int follow_link_flag)
+{
+ char *from_path_canon;
+ int ret;
+
+ if ((from_path_canon = do_realpath(from, from_path)) == NULL) {
+ error("Unable to canonicalize path \"%s\"", from_path);
+ return -1;
+ }
+
+ ret = crossload_dir_internal(from, to, from_path_canon, to_path, 0,
+ dirattrib, preserve_flag, print_flag, follow_link_flag);
+ free(from_path_canon);
+ return ret;
+}
+
char *
path_append(const char *p1, const char *p2)
{
@@ -1956,3 +2582,52 @@ path_append(const char *p1, const char *p2)
return(ret);
}
+char *
+make_absolute(char *p, const char *pwd)
+{
+ char *abs_str;
+
+ /* Derelativise */
+ if (p && !path_absolute(p)) {
+ abs_str = path_append(pwd, p);
+ free(p);
+ return(abs_str);
+ } else
+ return(p);
+}
+
+int
+remote_is_dir(struct sftp_conn *conn, const char *path)
+{
+ Attrib *a;
+
+ /* XXX: report errors? */
+ if ((a = do_stat(conn, path, 1)) == NULL)
+ return(0);
+ if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS))
+ return(0);
+ return(S_ISDIR(a->perm));
+}
+
+
+int
+local_is_dir(const char *path)
+{
+ struct stat sb;
+
+ /* XXX: report errors? */
+ if (stat(path, &sb) == -1)
+ return(0);
+
+ return(S_ISDIR(sb.st_mode));
+}
+
+/* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */
+int
+globpath_is_dir(const char *pathname)
+{
+ size_t l = strlen(pathname);
+
+ return l > 0 && pathname[l - 1] == '/';
+}
+
diff --git a/sftp-client.h b/sftp-client.h
index 63a9b8b13..7d0bd12ae 100644
--- a/sftp-client.h
+++ b/sftp-client.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-client.h,v 1.28 2019/01/16 23:23:45 djm Exp $ */
+/* $OpenBSD: sftp-client.h,v 1.34 2021/08/09 23:47:44 djm Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
@@ -53,6 +53,19 @@ struct sftp_statvfs {
u_int64_t f_namemax;
};
+/* Used for limits response on the wire from the server */
+struct sftp_limits {
+ u_int64_t packet_length;
+ u_int64_t read_length;
+ u_int64_t write_length;
+ u_int64_t open_handles;
+};
+
+/* print flag values */
+#define SFTP_QUIET 0 /* be quiet during transfers */
+#define SFTP_PRINT 1 /* list files and show progress bar */
+#define SFTP_PROGRESS_ONLY 2 /* progress bar only */
+
/*
* Initialise a SSH filexfer connection. Returns NULL on error or
* a pointer to a initialized sftp_conn struct on success.
@@ -61,6 +74,9 @@ struct sftp_conn *do_init(int, int, u_int, u_int, u_int64_t);
u_int sftp_proto_version(struct sftp_conn *);
+/* Query server limits */
+int do_limits(struct sftp_conn *, struct sftp_limits *);
+
/* Close file referred to by 'handle' */
int do_close(struct sftp_conn *, const u_char *, u_int);
@@ -97,11 +113,17 @@ int do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a);
/* Canonicalise 'path' - caller must free result */
char *do_realpath(struct sftp_conn *, const char *);
+/* Canonicalisation with tilde expansion (requires server extension) */
+char *do_expand_path(struct sftp_conn *, const char *);
+
+/* Returns non-zero if server can tilde-expand paths */
+int can_expand_path(struct sftp_conn *);
+
/* Get statistics for filesystem hosting file at "path" */
int do_statvfs(struct sftp_conn *, const char *, struct sftp_statvfs *, int);
/* Rename 'oldpath' to 'newpath' */
-int do_rename(struct sftp_conn *, const char *, const char *, int force_legacy);
+int do_rename(struct sftp_conn *, const char *, const char *, int);
/* Link 'oldpath' to 'newpath' */
int do_hardlink(struct sftp_conn *, const char *, const char *);
@@ -124,7 +146,7 @@ int do_download(struct sftp_conn *, const char *, const char *,
* times if 'pflag' is set
*/
int download_dir(struct sftp_conn *, const char *, const char *,
- Attrib *, int, int, int, int);
+ Attrib *, int, int, int, int, int);
/*
* Upload 'local_path' to 'remote_path'. Preserve permissions and times
@@ -137,9 +159,40 @@ int do_upload(struct sftp_conn *, const char *, const char *, int, int, int);
* times if 'pflag' is set
*/
int upload_dir(struct sftp_conn *, const char *, const char *, int, int, int,
- int);
+ int, int);
+
+/*
+ * Download a 'from_path' from the 'from' connection and upload it to
+ * to 'to' connection at 'to_path'.
+ */
+int
+do_crossload(struct sftp_conn *from, struct sftp_conn *to,
+ const char *from_path, const char *to_path,
+ Attrib *a, int preserve_flag);
+
+/*
+ * Recursively download a directory from 'from_path' from the 'from'
+ * connection and upload it to 'to' connection at 'to_path'.
+ */
+int crossload_dir(struct sftp_conn *from, struct sftp_conn *to,
+ const char *from_path, const char *to_path,
+ Attrib *dirattrib, int preserve_flag, int print_flag,
+ int follow_link_flag);
/* Concatenate paths, taking care of slashes. Caller must free result. */
char *path_append(const char *, const char *);
+/* Make absolute path if relative path and CWD is given. Does not modify
+ * original if the the path is already absolute. */
+char *make_absolute(char *, const char *);
+
+/* Check if remote path is directory */
+int remote_is_dir(struct sftp_conn *conn, const char *path);
+
+/* Check if local path is directory */
+int local_is_dir(const char *path);
+
+/* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */
+int globpath_is_dir(const char *pathname);
+
#endif
diff --git a/sftp-common.c b/sftp-common.c
index 677f27d63..3ad57673d 100644
--- a/sftp-common.c
+++ b/sftp-common.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-common.c,v 1.31 2018/09/13 15:23:32 millert Exp $ */
+/* $OpenBSD: sftp-common.c,v 1.32 2020/10/18 11:32:02 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2001 Damien Miller. All rights reserved.
@@ -136,7 +136,7 @@ decode_attrib(struct sshbuf *b, Attrib *a)
u_int i, count;
if ((r = sshbuf_get_u32(b, &count)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ return r;
for (i = 0; i < count; i++) {
if ((r = sshbuf_get_cstring(b, &type, NULL)) != 0 ||
(r = sshbuf_get_string(b, &data, &dlen)) != 0)
diff --git a/sftp-realpath.c b/sftp-realpath.c
index 9ac401812..2ec779d8f 100644
--- a/sftp-realpath.c
+++ b/sftp-realpath.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-realpath.c,v 1.1 2019/07/05 04:55:40 djm Exp $ */
+/* $OpenBSD: sftp-realpath.c,v 1.2 2021/09/02 21:03:54 deraadt Exp $ */
/*
* Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
*
@@ -30,7 +30,6 @@
#include "includes.h"
#include <sys/types.h>
-#include <sys/param.h>
#include <sys/stat.h>
#include <errno.h>
diff --git a/sftp-server.8 b/sftp-server.8
index 4a55dab26..5311bf929 100644
--- a/sftp-server.8
+++ b/sftp-server.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: sftp-server.8,v 1.28 2019/11/30 07:07:59 jmc Exp $
+.\" $OpenBSD: sftp-server.8,v 1.31 2021/07/27 14:14:25 jmc Exp $
.\"
.\" Copyright (c) 2000 Markus Friedl. All rights reserved.
.\"
@@ -22,7 +22,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 30 2019 $
+.Dd $Mdocdate: July 27 2021 $
.Dt SFTP-SERVER 8
.Os
.Sh NAME
@@ -35,8 +35,8 @@
.Op Fl d Ar start_directory
.Op Fl f Ar log_facility
.Op Fl l Ar log_level
-.Op Fl P Ar blacklisted_requests
-.Op Fl p Ar whitelisted_requests
+.Op Fl P Ar denied_requests
+.Op Fl p Ar allowed_requests
.Op Fl u Ar umask
.Ek
.Nm
@@ -64,7 +64,7 @@ for more information.
Valid options are:
.Bl -tag -width Ds
.It Fl d Ar start_directory
-specifies an alternate starting directory for users.
+Specifies an alternate starting directory for users.
The pathname may contain the following tokens that are expanded at runtime:
%% is replaced by a literal '%',
%d is replaced by the home directory of the user being authenticated,
@@ -99,30 +99,30 @@ performs on behalf of the client.
DEBUG and DEBUG1 are equivalent.
DEBUG2 and DEBUG3 each specify higher levels of debugging output.
The default is ERROR.
-.It Fl P Ar blacklisted_requests
-Specify a comma-separated list of SFTP protocol requests that are banned by
+.It Fl P Ar denied_requests
+Specifies a comma-separated list of SFTP protocol requests that are banned by
the server.
.Nm
-will reply to any blacklisted request with a failure.
+will reply to any denied request with a failure.
The
.Fl Q
flag can be used to determine the supported request types.
-If both a blacklist and a whitelist are specified, then the blacklist is
-applied before the whitelist.
-.It Fl p Ar whitelisted_requests
-Specify a comma-separated list of SFTP protocol requests that are permitted
+If both denied and allowed lists are specified, then the denied list is
+applied before the allowed list.
+.It Fl p Ar allowed_requests
+Specifies a comma-separated list of SFTP protocol requests that are permitted
by the server.
-All request types that are not on the whitelist will be logged and replied
+All request types that are not on the allowed list will be logged and replied
to with a failure message.
.Pp
Care must be taken when using this feature to ensure that requests made
implicitly by SFTP clients are permitted.
.It Fl Q Ar protocol_feature
-Query protocol features supported by
+Queries protocol features supported by
.Nm .
At present the only feature that may be queried is
.Dq requests ,
-which may be used for black or whitelisting (flags
+which may be used to deny or allow specific requests (flags
.Fl P
and
.Fl p
diff --git a/sftp-server.c b/sftp-server.c
index 359204fa7..18d194911 100644
--- a/sftp-server.c
+++ b/sftp-server.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-server.c,v 1.117 2019/07/05 04:55:40 djm Exp $ */
+/* $OpenBSD: sftp-server.c,v 1.129 2021/08/09 23:47:44 djm Exp $ */
/*
* Copyright (c) 2000-2004 Markus Friedl. All rights reserved.
*
@@ -19,6 +19,7 @@
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/resource.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
@@ -53,6 +54,9 @@
char *sftp_realpath(const char *, char *); /* sftp-realpath.c */
+/* Maximum data read that we are willing to accept */
+#define SFTP_MAX_READ_LENGTH (SFTP_MAX_MSG_LENGTH - 1024)
+
/* Our verbosity */
static LogLevel log_level = SYSLOG_LEVEL_ERROR;
@@ -74,7 +78,7 @@ static int init_done;
static int readonly;
/* Requests that are allowed/denied */
-static char *request_whitelist, *request_blacklist;
+static char *request_allowlist, *request_denylist;
/* portable attributes, etc. */
typedef struct Stat Stat;
@@ -110,6 +114,8 @@ static void process_extended_fstatvfs(u_int32_t id);
static void process_extended_hardlink(u_int32_t id);
static void process_extended_fsync(u_int32_t id);
static void process_extended_lsetstat(u_int32_t id);
+static void process_extended_limits(u_int32_t id);
+static void process_extended_expand(u_int32_t id);
static void process_extended(u_int32_t id);
struct sftp_handler {
@@ -146,15 +152,30 @@ static const struct sftp_handler handlers[] = {
/* SSH2_FXP_EXTENDED submessages */
static const struct sftp_handler extended_handlers[] = {
{ "posix-rename", "posix-rename@openssh.com", 0,
- process_extended_posix_rename, 1 },
+ process_extended_posix_rename, 1 },
{ "statvfs", "statvfs@openssh.com", 0, process_extended_statvfs, 0 },
{ "fstatvfs", "fstatvfs@openssh.com", 0, process_extended_fstatvfs, 0 },
{ "hardlink", "hardlink@openssh.com", 0, process_extended_hardlink, 1 },
{ "fsync", "fsync@openssh.com", 0, process_extended_fsync, 1 },
{ "lsetstat", "lsetstat@openssh.com", 0, process_extended_lsetstat, 1 },
+ { "limits", "limits@openssh.com", 0, process_extended_limits, 0 },
+ { "expand-path", "expand-path@openssh.com", 0,
+ process_extended_expand, 0 },
{ NULL, NULL, 0, NULL, 0 }
};
+static const struct sftp_handler *
+extended_handler_byname(const char *name)
+{
+ int i;
+
+ for (i = 0; extended_handlers[i].handler != NULL; i++) {
+ if (strcmp(name, extended_handlers[i].ext_name) == 0)
+ return &extended_handlers[i];
+ }
+ return NULL;
+}
+
static int
request_permitted(const struct sftp_handler *h)
{
@@ -164,20 +185,20 @@ request_permitted(const struct sftp_handler *h)
verbose("Refusing %s request in read-only mode", h->name);
return 0;
}
- if (request_blacklist != NULL &&
- ((result = match_list(h->name, request_blacklist, NULL))) != NULL) {
+ if (request_denylist != NULL &&
+ ((result = match_list(h->name, request_denylist, NULL))) != NULL) {
free(result);
- verbose("Refusing blacklisted %s request", h->name);
+ verbose("Refusing denylisted %s request", h->name);
return 0;
}
- if (request_whitelist != NULL &&
- ((result = match_list(h->name, request_whitelist, NULL))) != NULL) {
+ if (request_allowlist != NULL &&
+ ((result = match_list(h->name, request_allowlist, NULL))) != NULL) {
free(result);
- debug2("Permitting whitelisted %s request", h->name);
+ debug2("Permitting allowlisted %s request", h->name);
return 1;
}
- if (request_whitelist != NULL) {
- verbose("Refusing non-whitelisted %s request", h->name);
+ if (request_allowlist != NULL) {
+ verbose("Refusing non-allowlisted %s request", h->name);
return 0;
}
return 1;
@@ -489,7 +510,7 @@ send_msg(struct sshbuf *m)
int r;
if ((r = sshbuf_put_stringb(oqueue, m)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "enqueue");
sshbuf_reset(m);
}
@@ -522,16 +543,16 @@ send_status(u_int32_t id, u_int32_t status)
(status != SSH2_FX_OK && status != SSH2_FX_EOF))
logit("sent status %s", status_to_message(status));
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, SSH2_FXP_STATUS)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_u32(msg, status)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
if (version >= 3) {
if ((r = sshbuf_put_cstring(msg,
status_to_message(status))) != 0 ||
(r = sshbuf_put_cstring(msg, "")) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose message");
}
send_msg(msg);
sshbuf_free(msg);
@@ -543,11 +564,11 @@ send_data_or_handle(char type, u_int32_t id, const u_char *data, int dlen)
int r;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, type)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_string(msg, data, dlen)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
send_msg(msg);
sshbuf_free(msg);
}
@@ -578,17 +599,17 @@ send_names(u_int32_t id, int count, const Stat *stats)
int i, r;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, SSH2_FXP_NAME)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_u32(msg, count)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
debug("request %u: sent names count %d", id, count);
for (i = 0; i < count; i++) {
if ((r = sshbuf_put_cstring(msg, stats[i].name)) != 0 ||
(r = sshbuf_put_cstring(msg, stats[i].long_name)) != 0 ||
(r = encode_attrib(msg, &stats[i].attrib)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose filenames/attrib");
}
send_msg(msg);
sshbuf_free(msg);
@@ -602,11 +623,11 @@ send_attrib(u_int32_t id, const Attrib *a)
debug("request %u: sent attrib have 0x%x", id, a->flags);
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, SSH2_FXP_ATTRS)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = encode_attrib(msg, a)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
send_msg(msg);
sshbuf_free(msg);
}
@@ -622,7 +643,7 @@ send_statvfs(u_int32_t id, struct statvfs *st)
flag |= (st->f_flag & ST_NOSUID) ? SSH2_FXE_STATVFS_ST_NOSUID : 0;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 ||
(r = sshbuf_put_u32(msg, id)) != 0 ||
(r = sshbuf_put_u64(msg, st->f_bsize)) != 0 ||
@@ -636,11 +657,33 @@ send_statvfs(u_int32_t id, struct statvfs *st)
(r = sshbuf_put_u64(msg, FSID_TO_ULONG(st->f_fsid))) != 0 ||
(r = sshbuf_put_u64(msg, flag)) != 0 ||
(r = sshbuf_put_u64(msg, st->f_namemax)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
send_msg(msg);
sshbuf_free(msg);
}
+/*
+ * Prepare SSH2_FXP_VERSION extension advertisement for a single extension.
+ * The extension is checked for permission prior to advertisment.
+ */
+static int
+compose_extension(struct sshbuf *msg, const char *name, const char *ver)
+{
+ int r;
+ const struct sftp_handler *exthnd;
+
+ if ((exthnd = extended_handler_byname(name)) == NULL)
+ fatal_f("internal error: no handler for %s", name);
+ if (!request_permitted(exthnd)) {
+ debug2_f("refusing to advertise disallowed extension %s", name);
+ return 0;
+ }
+ if ((r = sshbuf_put_cstring(msg, name)) != 0 ||
+ (r = sshbuf_put_cstring(msg, ver)) != 0)
+ fatal_fr(r, "compose %s", name);
+ return 0;
+}
+
/* parse incoming */
static void
@@ -650,30 +693,24 @@ process_init(void)
int r;
if ((r = sshbuf_get_u32(iqueue, &version)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
verbose("received client version %u", version);
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, SSH2_FXP_VERSION)) != 0 ||
- (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0 ||
- /* POSIX rename extension */
- (r = sshbuf_put_cstring(msg, "posix-rename@openssh.com")) != 0 ||
- (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */
- /* statvfs extension */
- (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 ||
- (r = sshbuf_put_cstring(msg, "2")) != 0 || /* version */
- /* fstatvfs extension */
- (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 ||
- (r = sshbuf_put_cstring(msg, "2")) != 0 || /* version */
- /* hardlink extension */
- (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 ||
- (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */
- /* fsync extension */
- (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 ||
- (r = sshbuf_put_cstring(msg, "1")) != 0 || /* version */
- (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 ||
- (r = sshbuf_put_cstring(msg, "1")) != 0) /* version */
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0)
+ fatal_fr(r, "compose");
+
+ /* extension advertisments */
+ compose_extension(msg, "posix-rename@openssh.com", "1");
+ compose_extension(msg, "statvfs@openssh.com", "2");
+ compose_extension(msg, "fstatvfs@openssh.com", "2");
+ compose_extension(msg, "hardlink@openssh.com", "1");
+ compose_extension(msg, "fsync@openssh.com", "1");
+ compose_extension(msg, "lsetstat@openssh.com", "1");
+ compose_extension(msg, "limits@openssh.com", "1");
+ compose_extension(msg, "expand-path@openssh.com", "1");
+
send_msg(msg);
sshbuf_free(msg);
}
@@ -689,7 +726,7 @@ process_open(u_int32_t id)
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
(r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */
(r = decode_attrib(iqueue, &a)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug3("request %u: open flags %d", id, pflags);
flags = flags_from_portable(pflags);
@@ -726,7 +763,7 @@ process_close(u_int32_t id)
int r, handle, ret, status = SSH2_FX_FAILURE;
if ((r = get_handle(iqueue, &handle)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug3("request %u: close handle %u", id, handle);
handle_log_close(handle, NULL);
@@ -738,7 +775,8 @@ process_close(u_int32_t id)
static void
process_read(u_int32_t id)
{
- u_char buf[64*1024];
+ static u_char *buf;
+ static size_t buflen;
u_int32_t len;
int r, handle, fd, ret, status = SSH2_FX_FAILURE;
u_int64_t off;
@@ -746,32 +784,45 @@ process_read(u_int32_t id)
if ((r = get_handle(iqueue, &handle)) != 0 ||
(r = sshbuf_get_u64(iqueue, &off)) != 0 ||
(r = sshbuf_get_u32(iqueue, &len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
- debug("request %u: read \"%s\" (handle %d) off %llu len %d",
+ debug("request %u: read \"%s\" (handle %d) off %llu len %u",
id, handle_to_name(handle), handle, (unsigned long long)off, len);
- if (len > sizeof buf) {
- len = sizeof buf;
- debug2("read change len %d", len);
+ if ((fd = handle_to_fd(handle)) == -1)
+ goto out;
+ if (len > SFTP_MAX_READ_LENGTH) {
+ debug2("read change len %u to %u", len, SFTP_MAX_READ_LENGTH);
+ len = SFTP_MAX_READ_LENGTH;
}
- fd = handle_to_fd(handle);
- if (fd >= 0) {
- if (lseek(fd, off, SEEK_SET) == -1) {
- error("process_read: seek failed");
- status = errno_to_portable(errno);
- } else {
- ret = read(fd, buf, len);
- if (ret == -1) {
- status = errno_to_portable(errno);
- } else if (ret == 0) {
- status = SSH2_FX_EOF;
- } else {
- send_data(id, buf, ret);
- status = SSH2_FX_OK;
- handle_update_read(handle, ret);
- }
- }
+ if (len > buflen) {
+ debug3_f("allocate %zu => %u", buflen, len);
+ if ((buf = realloc(NULL, len)) == NULL)
+ fatal_f("realloc failed");
+ buflen = len;
+ }
+ if (lseek(fd, off, SEEK_SET) == -1) {
+ status = errno_to_portable(errno);
+ error_f("seek \"%.100s\": %s", handle_to_name(handle),
+ strerror(errno));
+ goto out;
}
+ if (len == 0) {
+ /* weird, but not strictly disallowed */
+ ret = 0;
+ } else if ((ret = read(fd, buf, len)) == -1) {
+ status = errno_to_portable(errno);
+ error_f("read \"%.100s\": %s", handle_to_name(handle),
+ strerror(errno));
+ goto out;
+ } else if (ret == 0) {
+ status = SSH2_FX_EOF;
+ goto out;
+ }
+ send_data(id, buf, ret);
+ handle_update_read(handle, ret);
+ /* success */
+ status = SSH2_FX_OK;
+ out:
if (status != SSH2_FX_OK)
send_status(id, status);
}
@@ -787,7 +838,7 @@ process_write(u_int32_t id)
if ((r = get_handle(iqueue, &handle)) != 0 ||
(r = sshbuf_get_u64(iqueue, &off)) != 0 ||
(r = sshbuf_get_string(iqueue, &data, &len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug("request %u: write \"%s\" (handle %d) off %llu len %zu",
id, handle_to_name(handle), handle, (unsigned long long)off, len);
@@ -797,20 +848,22 @@ process_write(u_int32_t id)
status = SSH2_FX_FAILURE;
else {
if (!(handle_to_flags(handle) & O_APPEND) &&
- lseek(fd, off, SEEK_SET) == -1) {
+ lseek(fd, off, SEEK_SET) == -1) {
status = errno_to_portable(errno);
- error("process_write: seek failed");
+ error_f("seek \"%.100s\": %s", handle_to_name(handle),
+ strerror(errno));
} else {
/* XXX ATOMICIO ? */
ret = write(fd, data, len);
if (ret == -1) {
- error("process_write: write failed");
status = errno_to_portable(errno);
+ error_f("write \"%.100s\": %s",
+ handle_to_name(handle), strerror(errno));
} else if ((size_t)ret == len) {
status = SSH2_FX_OK;
handle_update_write(handle, ret);
} else {
- debug2("nothing at all written");
+ debug2_f("nothing at all written");
status = SSH2_FX_FAILURE;
}
}
@@ -828,7 +881,7 @@ process_do_stat(u_int32_t id, int do_lstat)
int r, status = SSH2_FX_FAILURE;
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug3("request %u: %sstat", id, do_lstat ? "l" : "");
verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name);
@@ -865,7 +918,7 @@ process_fstat(u_int32_t id)
int fd, r, handle, status = SSH2_FX_FAILURE;
if ((r = get_handle(iqueue, &handle)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug("request %u: fstat \"%s\" (handle %u)",
id, handle_to_name(handle), handle);
fd = handle_to_fd(handle);
@@ -916,7 +969,7 @@ process_setstat(u_int32_t id)
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
(r = decode_attrib(iqueue, &a)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug("request %u: setstat name \"%s\"", id, name);
if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
@@ -963,7 +1016,7 @@ process_fsetstat(u_int32_t id)
if ((r = get_handle(iqueue, &handle)) != 0 ||
(r = decode_attrib(iqueue, &a)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug("request %u: fsetstat handle %d", id, handle);
fd = handle_to_fd(handle);
@@ -1027,7 +1080,7 @@ process_opendir(u_int32_t id)
int r, handle, status = SSH2_FX_FAILURE;
if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug3("request %u: opendir", id);
logit("opendir \"%s\"", path);
@@ -1058,7 +1111,7 @@ process_readdir(u_int32_t id)
int r, handle;
if ((r = get_handle(iqueue, &handle)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug("request %u: readdir \"%s\" (handle %d)", id,
handle_to_name(handle), handle);
@@ -1112,7 +1165,7 @@ process_remove(u_int32_t id)
int r, status = SSH2_FX_FAILURE;
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug3("request %u: remove", id);
logit("remove name \"%s\"", name);
@@ -1131,7 +1184,7 @@ process_mkdir(u_int32_t id)
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
(r = decode_attrib(iqueue, &a)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ?
a.perm & 07777 : 0777;
@@ -1150,7 +1203,7 @@ process_rmdir(u_int32_t id)
int r, status;
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug3("request %u: rmdir", id);
logit("rmdir name \"%s\"", name);
@@ -1168,7 +1221,7 @@ process_realpath(u_int32_t id)
int r;
if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (path[0] == '\0') {
free(path);
@@ -1196,7 +1249,7 @@ process_rename(u_int32_t id)
if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
(r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug3("request %u: rename", id);
logit("rename old \"%s\" new \"%s\"", oldpath, newpath);
@@ -1255,7 +1308,7 @@ process_readlink(u_int32_t id)
char *path;
if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug3("request %u: readlink", id);
verbose("readlink \"%s\"", path);
@@ -1280,7 +1333,7 @@ process_symlink(u_int32_t id)
if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
(r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug3("request %u: symlink", id);
logit("symlink old \"%s\" new \"%s\"", oldpath, newpath);
@@ -1300,7 +1353,7 @@ process_extended_posix_rename(u_int32_t id)
if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
(r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug3("request %u: posix-rename", id);
logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath);
@@ -1319,7 +1372,7 @@ process_extended_statvfs(u_int32_t id)
int r;
if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug3("request %u: statvfs", id);
logit("statvfs \"%s\"", path);
@@ -1327,7 +1380,7 @@ process_extended_statvfs(u_int32_t id)
send_status(id, errno_to_portable(errno));
else
send_statvfs(id, &st);
- free(path);
+ free(path);
}
static void
@@ -1337,7 +1390,7 @@ process_extended_fstatvfs(u_int32_t id)
struct statvfs st;
if ((r = get_handle(iqueue, &handle)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug("request %u: fstatvfs \"%s\" (handle %u)",
id, handle_to_name(handle), handle);
if ((fd = handle_to_fd(handle)) < 0) {
@@ -1358,7 +1411,7 @@ process_extended_hardlink(u_int32_t id)
if ((r = sshbuf_get_cstring(iqueue, &oldpath, NULL)) != 0 ||
(r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug3("request %u: hardlink", id);
logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath);
@@ -1375,7 +1428,7 @@ process_extended_fsync(u_int32_t id)
int handle, fd, r, status = SSH2_FX_OP_UNSUPPORTED;
if ((r = get_handle(iqueue, &handle)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug3("request %u: fsync (handle %u)", id, handle);
verbose("fsync \"%s\"", handle_to_name(handle));
if ((fd = handle_to_fd(handle)) < 0)
@@ -1396,7 +1449,7 @@ process_extended_lsetstat(u_int32_t id)
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
(r = decode_attrib(iqueue, &a)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug("request %u: lsetstat name \"%s\"", id, name);
if (a.flags & SSH2_FILEXFER_ATTR_SIZE) {
@@ -1437,25 +1490,113 @@ process_extended_lsetstat(u_int32_t id)
}
static void
+process_extended_limits(u_int32_t id)
+{
+ struct sshbuf *msg;
+ int r;
+ uint64_t nfiles = 0;
+#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
+ struct rlimit rlim;
+#endif
+
+ debug("request %u: limits", id);
+
+#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
+ if (getrlimit(RLIMIT_NOFILE, &rlim) != -1 && rlim.rlim_cur > 5)
+ nfiles = rlim.rlim_cur - 5; /* stdio(3) + syslog + spare */
+#endif
+
+ if ((msg = sshbuf_new()) == NULL)
+ fatal_f("sshbuf_new failed");
+ if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED_REPLY)) != 0 ||
+ (r = sshbuf_put_u32(msg, id)) != 0 ||
+ /* max-packet-length */
+ (r = sshbuf_put_u64(msg, SFTP_MAX_MSG_LENGTH)) != 0 ||
+ /* max-read-length */
+ (r = sshbuf_put_u64(msg, SFTP_MAX_READ_LENGTH)) != 0 ||
+ /* max-write-length */
+ (r = sshbuf_put_u64(msg, SFTP_MAX_MSG_LENGTH - 1024)) != 0 ||
+ /* max-open-handles */
+ (r = sshbuf_put_u64(msg, nfiles)) != 0)
+ fatal_fr(r, "compose");
+ send_msg(msg);
+ sshbuf_free(msg);
+}
+
+static void
+process_extended_expand(u_int32_t id)
+{
+ char cwd[PATH_MAX], resolvedname[PATH_MAX];
+ char *path, *npath;
+ int r;
+ Stat s;
+
+ if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0)
+ fatal_fr(r, "parse");
+ if (getcwd(cwd, sizeof(cwd)) == NULL) {
+ send_status(id, errno_to_portable(errno));
+ goto out;
+ }
+
+ debug3("request %u: expand, original \"%s\"", id, path);
+ if (path[0] == '\0') {
+ /* empty path */
+ free(path);
+ path = xstrdup(".");
+ } else if (*path == '~') {
+ /* ~ expand path */
+ /* Special-case for "~" and "~/" to respect homedir flag */
+ if (strcmp(path, "~") == 0) {
+ free(path);
+ path = xstrdup(cwd);
+ } else if (strncmp(path, "~/", 2) == 0) {
+ npath = xstrdup(path + 2);
+ free(path);
+ xasprintf(&path, "%s/%s", cwd, npath);
+ } else {
+ /* ~user expansions */
+ if (tilde_expand(path, pw->pw_uid, &npath) != 0) {
+ send_status(id, errno_to_portable(EINVAL));
+ goto out;
+ }
+ free(path);
+ path = npath;
+ }
+ } else if (*path != '/') {
+ /* relative path */
+ xasprintf(&npath, "%s/%s", cwd, path);
+ free(path);
+ path = npath;
+ }
+ verbose("expand \"%s\"", path);
+ if (sftp_realpath(path, resolvedname) == NULL) {
+ send_status(id, errno_to_portable(errno));
+ goto out;
+ }
+ attrib_clear(&s.attrib);
+ s.name = s.long_name = resolvedname;
+ send_names(id, 1, &s);
+ out:
+ free(path);
+}
+
+static void
process_extended(u_int32_t id)
{
char *request;
- int i, r;
+ int r;
+ const struct sftp_handler *exthand;
if ((r = sshbuf_get_cstring(iqueue, &request, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- for (i = 0; extended_handlers[i].handler != NULL; i++) {
- if (strcmp(request, extended_handlers[i].ext_name) == 0) {
- if (!request_permitted(&extended_handlers[i]))
- send_status(id, SSH2_FX_PERMISSION_DENIED);
- else
- extended_handlers[i].handler(id);
- break;
- }
- }
- if (extended_handlers[i].handler == NULL) {
+ fatal_fr(r, "parse");
+ if ((exthand = extended_handler_byname(request)) == NULL) {
error("Unknown extended request \"%.100s\"", request);
send_status(id, SSH2_FX_OP_UNSUPPORTED); /* MUST */
+ } else {
+ if (!request_permitted(exthand))
+ send_status(id, SSH2_FX_PERMISSION_DENIED);
+ else
+ exthand->handler(id);
}
free(request);
}
@@ -1486,10 +1627,10 @@ process(void)
if (buf_len < msg_len + 4)
return;
if ((r = sshbuf_consume(iqueue, 4)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "consume");
buf_len -= 4;
if ((r = sshbuf_get_u8(iqueue, &type)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse type");
switch (type) {
case SSH2_FXP_INIT:
@@ -1500,14 +1641,14 @@ process(void)
if (!init_done)
fatal("Received extended request before init");
if ((r = sshbuf_get_u32(iqueue, &id)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse extended ID");
process_extended(id);
break;
default:
if (!init_done)
fatal("Received %u request before init", type);
if ((r = sshbuf_get_u32(iqueue, &id)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse ID");
for (i = 0; handlers[i].handler != NULL; i++) {
if (type == handlers[i].type) {
if (!request_permitted(&handlers[i])) {
@@ -1534,7 +1675,7 @@ process(void)
}
if (msg_len > consumed &&
(r = sshbuf_consume(iqueue, msg_len - consumed)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "consume");
}
/* Cleanup handler that logs active handles upon normal exit */
@@ -1556,8 +1697,8 @@ sftp_server_usage(void)
fprintf(stderr,
"usage: %s [-ehR] [-d start_directory] [-f log_facility] "
- "[-l log_level]\n\t[-P blacklisted_requests] "
- "[-p whitelisted_requests] [-u umask]\n"
+ "[-l log_level]\n\t[-P denied_requests] "
+ "[-p allowed_requests] [-u umask]\n"
" %s -Q protocol_feature\n",
__progname, __progname);
exit(1);
@@ -1627,14 +1768,14 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
free(cp);
break;
case 'p':
- if (request_whitelist != NULL)
+ if (request_allowlist != NULL)
fatal("Permitted requests already set");
- request_whitelist = xstrdup(optarg);
+ request_allowlist = xstrdup(optarg);
break;
case 'P':
- if (request_blacklist != NULL)
+ if (request_denylist != NULL)
fatal("Refused requests already set");
- request_blacklist = xstrdup(optarg);
+ request_denylist = xstrdup(optarg);
break;
case 'u':
errno = 0;
@@ -1692,9 +1833,9 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
max = out;
if ((iqueue = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((oqueue = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
rset = xcalloc(howmany(max + 1, NFDBITS), sizeof(fd_mask));
wset = xcalloc(howmany(max + 1, NFDBITS), sizeof(fd_mask));
@@ -1721,8 +1862,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
SFTP_MAX_MSG_LENGTH)) == 0)
FD_SET(in, rset);
else if (r != SSH_ERR_NO_BUFFER_SPACE)
- fatal("%s: sshbuf_check_reserve failed: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "reserve");
olen = sshbuf_len(oqueue);
if (olen > 0)
@@ -1744,10 +1884,8 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
} else if (len == -1) {
error("read: %s", strerror(errno));
sftp_server_cleanup_exit(1);
- } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) {
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
- }
+ } else if ((r = sshbuf_put(iqueue, buf, len)) != 0)
+ fatal_fr(r, "sshbuf_put");
}
/* send oqueue to stdout */
if (FD_ISSET(out, wset)) {
@@ -1755,10 +1893,8 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
if (len == -1) {
error("write: %s", strerror(errno));
sftp_server_cleanup_exit(1);
- } else if ((r = sshbuf_consume(oqueue, len)) != 0) {
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
- }
+ } else if ((r = sshbuf_consume(oqueue, len)) != 0)
+ fatal_fr(r, "consume");
}
/*
@@ -1770,7 +1906,6 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
if (r == 0)
process();
else if (r != SSH_ERR_NO_BUFFER_SPACE)
- fatal("%s: sshbuf_check_reserve: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "reserve");
}
}
diff --git a/sftp.1 b/sftp.1
index a305b37d1..7eebeeacb 100644
--- a/sftp.1
+++ b/sftp.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: sftp.1,v 1.131 2020/04/23 21:28:09 jmc Exp $
+.\" $OpenBSD: sftp.1,v 1.138 2021/07/02 05:11:21 dtucker Exp $
.\"
.\" Copyright (c) 2001 Damien Miller. All rights reserved.
.\"
@@ -22,7 +22,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: April 23 2020 $
+.Dd $Mdocdate: July 2 2021 $
.Dt SFTP 1
.Os
.Sh NAME
@@ -30,7 +30,7 @@
.Nd OpenSSH secure file transfer
.Sh SYNOPSIS
.Nm sftp
-.Op Fl 46aCfNpqrv
+.Op Fl 46AaCfNpqrv
.Op Fl B Ar buffer_size
.Op Fl b Ar batchfile
.Op Fl c Ar cipher
@@ -104,6 +104,11 @@ to use IPv4 addresses only.
Forces
.Nm
to use IPv6 addresses only.
+.It Fl A
+Allows forwarding of
+.Xr ssh-agent 1
+to the remote system.
+The default is not to forward an authentication agent.
.It Fl a
Attempt to continue interrupted transfers rather than overwriting
existing partial or complete copies of files.
@@ -227,7 +232,6 @@ For full details of the options listed below, and their possible values, see
.It CanonicalizePermittedCNAMEs
.It CASignatureAlgorithms
.It CertificateFile
-.It ChallengeResponseAuthentication
.It CheckHostIP
.It Ciphers
.It Compression
@@ -241,8 +245,8 @@ For full details of the options listed below, and their possible values, see
.It GSSAPIDelegateCredentials
.It HashKnownHosts
.It Host
+.It HostbasedAcceptedAlgorithms
.It HostbasedAuthentication
-.It HostbasedKeyTypes
.It HostKeyAlgorithms
.It HostKeyAlias
.It Hostname
@@ -253,6 +257,7 @@ For full details of the options listed below, and their possible values, see
.It KbdInteractiveAuthentication
.It KbdInteractiveDevices
.It KexAlgorithms
+.It KnownHostsCommand
.It LogLevel
.It MACs
.It NoHostAuthenticationForLocalhost
@@ -263,7 +268,7 @@ For full details of the options listed below, and their possible values, see
.It PreferredAuthentications
.It ProxyCommand
.It ProxyJump
-.It PubkeyAcceptedKeyTypes
+.It PubkeyAcceptedAlgorithms
.It PubkeyAuthentication
.It RekeyLimit
.It SendEnv
@@ -343,15 +348,18 @@ Change group of file
.Ar path
to
.Ar grp .
-If the
-.Fl h
-flag is specified, then symlinks will not be followed.
.Ar path
may contain
.Xr glob 7
characters and may match multiple files.
.Ar grp
must be a numeric GID.
+.Pp
+If the
+.Fl h
+flag is specified, then symlinks will not be followed.
+Note that this is only supported by servers that implement
+the "lsetstat@openssh.com" extension.
.It Xo Ic chmod
.Op Fl h
.Ar mode
@@ -361,13 +369,16 @@ Change permissions of file
.Ar path
to
.Ar mode .
-If the
-.Fl h
-flag is specified, then symlinks will not be followed.
.Ar path
may contain
.Xr glob 7
characters and may match multiple files.
+.Pp
+If the
+.Fl h
+flag is specified, then symlinks will not be followed.
+Note that this is only supported by servers that implement
+the "lsetstat@openssh.com" extension.
.It Xo Ic chown
.Op Fl h
.Ar own
@@ -377,15 +388,18 @@ Change owner of file
.Ar path
to
.Ar own .
-If the
-.Fl h
-flag is specified, then symlinks will not be followed.
.Ar path
may contain
.Xr glob 7
characters and may match multiple files.
.Ar own
must be a numeric UID.
+.Pp
+If the
+.Fl h
+flag is specified, then symlinks will not be followed.
+Note that this is only supported by servers that implement
+the "lsetstat@openssh.com" extension.
.It Xo Ic df
.Op Fl hi
.Op Ar path
diff --git a/sftp.c b/sftp.c
index 2799e4a10..418f312f7 100644
--- a/sftp.c
+++ b/sftp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp.c,v 1.200 2020/04/03 05:53:52 jmc Exp $ */
+/* $OpenBSD: sftp.c,v 1.212 2021/09/11 09:05:50 schwarze Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
@@ -70,9 +70,6 @@ typedef void EditLine;
#include "sftp-common.h"
#include "sftp-client.h"
-#define DEFAULT_COPY_BUFLEN 32768 /* Size of buffer for up/download */
-#define DEFAULT_NUM_REQUESTS 64 /* # concurrent outstanding requests */
-
/* File to read commands from */
FILE* infile;
@@ -82,7 +79,7 @@ int batchmode = 0;
/* PID of ssh transport process */
static volatile pid_t sshpid = -1;
-/* Suppress diagnositic messages */
+/* Suppress diagnostic messages */
int quiet = 0;
/* This is set to 0 if the progressmeter is not desired. */
@@ -255,6 +252,13 @@ cmd_interrupt(int signo)
errno = olderrno;
}
+/* ARGSUSED */
+static void
+read_interrupt(int signo)
+{
+ interrupted = 1;
+}
+
/*ARGSUSED*/
static void
sigchld_handler(int sig)
@@ -385,20 +389,6 @@ path_strip(const char *path, const char *strip)
return (xstrdup(path));
}
-static char *
-make_absolute(char *p, const char *pwd)
-{
- char *abs_str;
-
- /* Derelativise */
- if (p && !path_absolute(p)) {
- abs_str = path_append(pwd, p);
- free(p);
- return(abs_str);
- } else
- return(p);
-}
-
static int
parse_getput_flags(const char *cmd, char **argv, int argc,
int *aflag, int *fflag, int *pflag, int *rflag)
@@ -608,40 +598,6 @@ parse_no_flags(const char *cmd, char **argv, int argc)
}
static int
-is_dir(const char *path)
-{
- struct stat sb;
-
- /* XXX: report errors? */
- if (stat(path, &sb) == -1)
- return(0);
-
- return(S_ISDIR(sb.st_mode));
-}
-
-static int
-remote_is_dir(struct sftp_conn *conn, const char *path)
-{
- Attrib *a;
-
- /* XXX: report errors? */
- if ((a = do_stat(conn, path, 1)) == NULL)
- return(0);
- if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS))
- return(0);
- return(S_ISDIR(a->perm));
-}
-
-/* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */
-static int
-pathname_is_dir(const char *pathname)
-{
- size_t l = strlen(pathname);
-
- return l > 0 && pathname[l - 1] == '/';
-}
-
-static int
process_get(struct sftp_conn *conn, const char *src, const char *dst,
const char *pwd, int pflag, int rflag, int resume, int fflag)
{
@@ -670,7 +626,7 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst,
* If multiple matches then dst must be a directory or
* unspecified.
*/
- if (g.gl_matchc > 1 && dst != NULL && !is_dir(dst)) {
+ if (g.gl_matchc > 1 && dst != NULL && !local_is_dir(dst)) {
error("Multiple source paths, but destination "
"\"%s\" is not a directory", dst);
err = -1;
@@ -687,7 +643,7 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst,
}
if (g.gl_matchc == 1 && dst) {
- if (is_dir(dst)) {
+ if (local_is_dir(dst)) {
abs_dst = path_append(dst, filename);
} else {
abs_dst = xstrdup(dst);
@@ -706,10 +662,11 @@ process_get(struct sftp_conn *conn, const char *src, const char *dst,
else if (!quiet && !resume)
mprintf("Fetching %s to %s\n",
g.gl_pathv[i], abs_dst);
- if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
+ /* XXX follow link flag */
+ if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL,
pflag || global_pflag, 1, resume,
- fflag || global_fflag) == -1)
+ fflag || global_fflag, 0) == -1)
err = -1;
} else {
if (do_download(conn, g.gl_pathv[i], abs_dst, NULL,
@@ -792,17 +749,18 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst,
}
free(tmp);
- resume |= global_aflag;
+ resume |= global_aflag;
if (!quiet && resume)
mprintf("Resuming upload of %s to %s\n",
g.gl_pathv[i], abs_dst);
else if (!quiet && !resume)
mprintf("Uploading %s to %s\n",
g.gl_pathv[i], abs_dst);
- if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
+ /* XXX follow_link_flag */
+ if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
if (upload_dir(conn, g.gl_pathv[i], abs_dst,
pflag || global_pflag, 1, resume,
- fflag || global_fflag) == -1)
+ fflag || global_fflag, 0) == -1)
err = -1;
} else {
if (do_upload(conn, g.gl_pathv[i], abs_dst,
@@ -939,7 +897,10 @@ sglob_comp(const void *aa, const void *bb)
return (rmul * strcmp(ap, bp));
else if (sort_flag & LS_TIME_SORT) {
#if defined(HAVE_STRUCT_STAT_ST_MTIM)
- return (rmul * timespeccmp(&as->st_mtim, &bs->st_mtim, <));
+ if (timespeccmp(&as->st_mtim, &bs->st_mtim, ==))
+ return 0;
+ return timespeccmp(&as->st_mtim, &bs->st_mtim, <) ?
+ rmul : -rmul;
#elif defined(HAVE_STRUCT_STAT_ST_MTIME)
return (rmul * NCMP(as->st_mtime, bs->st_mtime));
#else
@@ -1172,7 +1133,7 @@ undo_glob_escape(char *s)
* last argument's quote has been properly terminated or 0 otherwise.
* This parameter is only of use if "sloppy" is set.
*/
-#define MAXARGS 128
+#define MAXARGS 128
#define MAXARGLEN 8192
static char **
makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
@@ -1330,7 +1291,7 @@ parse_args(const char **cpp, int *ignore_errors, int *disable_echo, int *aflag,
const char *cmd, *cp = *cpp;
char *cp2, **argv;
int base = 0;
- long l;
+ long long ll;
int path1_mandatory = 0, i, cmdnum, optidx, argc;
/* Skip leading whitespace */
@@ -1488,16 +1449,16 @@ parse_args(const char **cpp, int *ignore_errors, int *disable_echo, int *aflag,
if (argc - optidx < 1)
goto need_num_arg;
errno = 0;
- l = strtol(argv[optidx], &cp2, base);
+ ll = strtoll(argv[optidx], &cp2, base);
if (cp2 == argv[optidx] || *cp2 != '\0' ||
- ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) ||
- l < 0) {
+ ((ll == LLONG_MIN || ll == LLONG_MAX) && errno == ERANGE) ||
+ ll < 0 || ll > UINT32_MAX) {
need_num_arg:
error("You must supply a numeric argument "
"to the %s command.", cmd);
return -1;
}
- *n_arg = l;
+ *n_arg = ll;
if (cmdnum == I_LUMASK)
break;
/* Get pathname (mandatory) */
@@ -2101,7 +2062,7 @@ complete(EditLine *el, int ch)
lf = el_line(el);
if (el_get(el, EL_CLIENTDATA, (void**)&complete_ctx) != 0)
- fatal("%s: el_get failed", __func__);
+ fatal_f("el_get failed");
/* Figure out which argument the cursor points to */
cursor = lf->cursor - lf->buffer;
@@ -2243,14 +2204,24 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
interactive = !batchmode && isatty(STDIN_FILENO);
err = 0;
for (;;) {
- ssh_signal(SIGINT, SIG_IGN);
+ struct sigaction sa;
+ interrupted = 0;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = interactive ? read_interrupt : killchild;
+ if (sigaction(SIGINT, &sa, NULL) == -1) {
+ debug3("sigaction(%s): %s", strsignal(SIGINT),
+ strerror(errno));
+ break;
+ }
if (el == NULL) {
if (interactive)
printf("sftp> ");
if (fgets(cmd, sizeof(cmd), infile) == NULL) {
if (interactive)
printf("\n");
+ if (interrupted)
+ continue;
break;
}
} else {
@@ -2261,7 +2232,9 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2)
if ((line = el_gets(el, &count)) == NULL ||
count <= 0) {
printf("\n");
- break;
+ if (interrupted)
+ continue;
+ break;
}
history(hl, &hev, H_ENTER, line);
if (strlcpy(cmd, line, sizeof(cmd)) >= sizeof(cmd)) {
@@ -2363,7 +2336,7 @@ usage(void)
extern char *__progname;
fprintf(stderr,
- "usage: %s [-46aCfNpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n"
+ "usage: %s [-46AaCfNpqrv] [-B buffer_size] [-b batchfile] [-c cipher]\n"
" [-D sftp_server_path] [-F ssh_config] [-i identity_file]\n"
" [-J destination] [-l limit] [-o ssh_option] [-P port]\n"
" [-R num_requests] [-S program] [-s subsystem | sftp_server]\n"
@@ -2386,8 +2359,8 @@ main(int argc, char **argv)
extern int optind;
extern char *optarg;
struct sftp_conn *conn;
- size_t copy_buffer_len = DEFAULT_COPY_BUFLEN;
- size_t num_requests = DEFAULT_NUM_REQUESTS;
+ size_t copy_buffer_len = 0;
+ size_t num_requests = 0;
long long limit_kbps = 0;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
@@ -2401,7 +2374,6 @@ main(int argc, char **argv)
args.list = NULL;
addargs(&args, "%s", ssh_program);
addargs(&args, "-oForwardX11 no");
- addargs(&args, "-oForwardAgent no");
addargs(&args, "-oPermitLocalCommand no");
addargs(&args, "-oClearAllForwardings yes");
@@ -2409,9 +2381,10 @@ main(int argc, char **argv)
infile = stdin;
while ((ch = getopt(argc, argv,
- "1246afhNpqrvCc:D:i:l:o:s:S:b:B:F:J:P:R:")) != -1) {
+ "1246AafhNpqrvCc:D:i:l:o:s:S:b:B:F:J:P:R:")) != -1) {
switch (ch) {
/* Passed through to ssh(1) */
+ case 'A':
case '4':
case '6':
case 'C':
@@ -2511,6 +2484,9 @@ main(int argc, char **argv)
}
}
+ /* Do this last because we want the user to be able to override it */
+ addargs(&args, "-oForwardAgent no");
+
if (!isatty(STDERR_FILENO))
showprogress = 0;
diff --git a/sk-api.h b/sk-api.h
index 1ecaa3537..74921d4c3 100644
--- a/sk-api.h
+++ b/sk-api.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sk-api.h,v 1.9 2020/04/28 04:02:29 djm Exp $ */
+/* $OpenBSD: sk-api.h,v 1.12 2021/02/18 02:15:07 djm Exp $ */
/*
* Copyright (c) 2019 Google LLC
*
@@ -47,6 +47,8 @@ struct sk_enroll_response {
size_t signature_len;
uint8_t *attestation_cert;
size_t attestation_cert_len;
+ uint8_t *authdata;
+ size_t authdata_len;
};
struct sk_sign_response {
@@ -63,6 +65,7 @@ struct sk_resident_key {
size_t slot;
char *application;
struct sk_enroll_response key;
+ uint8_t flags;
};
struct sk_option {
@@ -71,7 +74,7 @@ struct sk_option {
uint8_t required;
};
-#define SSH_SK_VERSION_MAJOR 0x00050000 /* current API version */
+#define SSH_SK_VERSION_MAJOR 0x00070000 /* current API version */
#define SSH_SK_VERSION_MAJOR_MASK 0xffff0000
/* Return the version of the middleware API */
@@ -83,7 +86,7 @@ int sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
struct sk_option **options, struct sk_enroll_response **enroll_response);
/* Sign a challenge */
-int sk_sign(uint32_t alg, const uint8_t *message, size_t message_len,
+int sk_sign(uint32_t alg, const uint8_t *data, size_t data_len,
const char *application, const uint8_t *key_handle, size_t key_handle_len,
uint8_t flags, const char *pin, struct sk_option **options,
struct sk_sign_response **sign_response);
diff --git a/sk-usbhid.c b/sk-usbhid.c
index 25250824d..438980889 100644
--- a/sk-usbhid.c
+++ b/sk-usbhid.c
@@ -1,5 +1,7 @@
+/* $OpenBSD: sk-usbhid.c,v 1.30 2021/05/31 06:48:42 djm Exp $ */
/*
* Copyright (c) 2019 Markus Friedl
+ * Copyright (c) 2020 Pedro Martelletto
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -24,6 +26,7 @@
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
+#include <time.h>
#ifdef HAVE_SHA2_H
#include <sha2.h>
#endif
@@ -40,9 +43,33 @@
#include <fido.h>
#include <fido/credman.h>
+/* backwards compat for libfido2 */
+#ifndef HAVE_FIDO_CRED_PROT
+#define fido_cred_prot(x) (0)
+#endif
+#ifndef HAVE_FIDO_CRED_SET_PROT
+#define fido_cred_set_prot(x, y) (FIDO_ERR_UNSUPPORTED_OPTION)
+#endif
+#ifndef HAVE_FIDO_DEV_SUPPORTS_CRED_PROT
+#define fido_dev_supports_cred_prot(x) (0)
+#endif
+#ifndef HAVE_FIDO_DEV_GET_TOUCH_BEGIN
+#define fido_dev_get_touch_begin(x) (FIDO_ERR_UNSUPPORTED_OPTION)
+#endif
+#ifndef HAVE_FIDO_DEV_GET_TOUCH_STATUS
+#define fido_dev_get_touch_status(x, y, z) (FIDO_ERR_UNSUPPORTED_OPTION)
+#endif
+#ifndef FIDO_CRED_PROT_UV_REQUIRED
+#define FIDO_CRED_PROT_UV_REQUIRED 0
+#endif
+#ifndef FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID
+#define FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID 0
+#endif
+
#ifndef SK_STANDALONE
# include "log.h"
# include "xmalloc.h"
+# include "misc.h"
/*
* If building as part of OpenSSH, then rename exported functions.
* This must be done before including sk-api.h.
@@ -57,7 +84,16 @@
/* #define SK_DEBUG 1 */
-#define MAX_FIDO_DEVICES 256
+#ifdef SK_DEBUG
+#define SSH_FIDO_INIT_ARG FIDO_DEBUG
+#else
+#define SSH_FIDO_INIT_ARG 0
+#endif
+
+#define MAX_FIDO_DEVICES 8
+#define FIDO_POLL_MS 50
+#define SELECT_MS 15000
+#define POLL_SLEEP_NS 200000000
/* Compatibility with OpenSSH 1.0.x */
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
@@ -68,6 +104,11 @@
} while (0)
#endif
+struct sk_usbhid {
+ fido_dev_t *dev;
+ char *path;
+};
+
/* Return the version of the middleware API */
uint32_t sk_api_version(void);
@@ -77,7 +118,7 @@ int sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
struct sk_option **options, struct sk_enroll_response **enroll_response);
/* Sign a challenge */
-int sk_sign(uint32_t alg, const uint8_t *message, size_t message_len,
+int sk_sign(uint32_t alg, const uint8_t *data, size_t data_len,
const char *application, const uint8_t *key_handle, size_t key_handle_len,
uint8_t flags, const char *pin, struct sk_option **options,
struct sk_sign_response **sign_response);
@@ -121,53 +162,185 @@ sk_api_version(void)
return SSH_SK_VERSION_MAJOR;
}
-/* Select the first identified FIDO device attached to the system */
-static char *
-pick_first_device(void)
+static struct sk_usbhid *
+sk_open(const char *path)
{
- char *ret = NULL;
- fido_dev_info_t *devlist = NULL;
- size_t olen = 0;
+ struct sk_usbhid *sk;
int r;
- const fido_dev_info_t *di;
- if ((devlist = fido_dev_info_new(1)) == NULL) {
- skdebug(__func__, "fido_dev_info_new failed");
- goto out;
+ if (path == NULL) {
+ skdebug(__func__, "path == NULL");
+ return NULL;
}
- if ((r = fido_dev_info_manifest(devlist, 1, &olen)) != FIDO_OK) {
- skdebug(__func__, "fido_dev_info_manifest failed: %s",
+ if ((sk = calloc(1, sizeof(*sk))) == NULL) {
+ skdebug(__func__, "calloc sk failed");
+ return NULL;
+ }
+ if ((sk->path = strdup(path)) == NULL) {
+ skdebug(__func__, "strdup path failed");
+ free(sk);
+ return NULL;
+ }
+ if ((sk->dev = fido_dev_new()) == NULL) {
+ skdebug(__func__, "fido_dev_new failed");
+ free(sk->path);
+ free(sk);
+ return NULL;
+ }
+ if ((r = fido_dev_open(sk->dev, sk->path)) != FIDO_OK) {
+ skdebug(__func__, "fido_dev_open %s failed: %s", sk->path,
fido_strerr(r));
- goto out;
+ fido_dev_free(&sk->dev);
+ free(sk->path);
+ free(sk);
+ return NULL;
}
- if (olen != 1) {
- skdebug(__func__, "fido_dev_info_manifest bad len %zu", olen);
- goto out;
+ return sk;
+}
+
+static void
+sk_close(struct sk_usbhid *sk)
+{
+ if (sk == NULL)
+ return;
+ fido_dev_cancel(sk->dev); /* cancel any pending operation */
+ fido_dev_close(sk->dev);
+ fido_dev_free(&sk->dev);
+ free(sk->path);
+ free(sk);
+}
+
+static struct sk_usbhid **
+sk_openv(const fido_dev_info_t *devlist, size_t ndevs, size_t *nopen)
+{
+ const fido_dev_info_t *di;
+ struct sk_usbhid **skv;
+ size_t i;
+
+ *nopen = 0;
+ if ((skv = calloc(ndevs, sizeof(*skv))) == NULL) {
+ skdebug(__func__, "calloc skv failed");
+ return NULL;
}
- di = fido_dev_info_ptr(devlist, 0);
- if ((ret = strdup(fido_dev_info_path(di))) == NULL) {
- skdebug(__func__, "fido_dev_info_path failed");
- goto out;
+ for (i = 0; i < ndevs; i++) {
+ if ((di = fido_dev_info_ptr(devlist, i)) == NULL)
+ skdebug(__func__, "fido_dev_info_ptr failed");
+ else if ((skv[*nopen] = sk_open(fido_dev_info_path(di))) == NULL)
+ skdebug(__func__, "sk_open failed");
+ else
+ (*nopen)++;
}
- out:
- fido_dev_info_free(&devlist, 1);
- return ret;
+ if (*nopen == 0) {
+ for (i = 0; i < ndevs; i++)
+ sk_close(skv[i]);
+ free(skv);
+ skv = NULL;
+ }
+
+ return skv;
+}
+
+static void
+sk_closev(struct sk_usbhid **skv, size_t nsk)
+{
+ size_t i;
+
+ for (i = 0; i < nsk; i++)
+ sk_close(skv[i]);
+ free(skv);
}
-/* Check if the specified key handle exists on a given device. */
static int
-try_device(fido_dev_t *dev, const uint8_t *message, size_t message_len,
- const char *application, const uint8_t *key_handle, size_t key_handle_len)
+sk_touch_begin(struct sk_usbhid **skv, size_t nsk)
+{
+ size_t i, ok = 0;
+ int r;
+
+ for (i = 0; i < nsk; i++)
+ if ((r = fido_dev_get_touch_begin(skv[i]->dev)) != FIDO_OK)
+ skdebug(__func__, "fido_dev_get_touch_begin %s failed:"
+ " %s", skv[i]->path, fido_strerr(r));
+ else
+ ok++;
+
+ return ok ? 0 : -1;
+}
+
+static int
+sk_touch_poll(struct sk_usbhid **skv, size_t nsk, int *touch, size_t *idx)
+{
+ struct timespec ts_pause;
+ size_t npoll, i;
+ int r;
+
+ ts_pause.tv_sec = 0;
+ ts_pause.tv_nsec = POLL_SLEEP_NS;
+ nanosleep(&ts_pause, NULL);
+ npoll = nsk;
+ for (i = 0; i < nsk; i++) {
+ if (skv[i] == NULL)
+ continue; /* device discarded */
+ skdebug(__func__, "polling %s", skv[i]->path);
+ if ((r = fido_dev_get_touch_status(skv[i]->dev, touch,
+ FIDO_POLL_MS)) != FIDO_OK) {
+ skdebug(__func__, "fido_dev_get_touch_status %s: %s",
+ skv[i]->path, fido_strerr(r));
+ sk_close(skv[i]); /* discard device */
+ skv[i] = NULL;
+ if (--npoll == 0) {
+ skdebug(__func__, "no device left to poll");
+ return -1;
+ }
+ } else if (*touch) {
+ *idx = i;
+ return 0;
+ }
+ }
+ *touch = 0;
+ return 0;
+}
+
+/* Calculate SHA256(m) */
+static int
+sha256_mem(const void *m, size_t mlen, u_char *d, size_t dlen)
+{
+#ifdef WITH_OPENSSL
+ u_int mdlen;
+#endif
+
+ if (dlen != 32)
+ return -1;
+#ifdef WITH_OPENSSL
+ mdlen = dlen;
+ if (!EVP_Digest(m, mlen, d, &mdlen, EVP_sha256(), NULL))
+ return -1;
+#else
+ SHA256Data(m, mlen, d);
+#endif
+ return 0;
+}
+
+/* Check if the specified key handle exists on a given sk. */
+static int
+sk_try(const struct sk_usbhid *sk, const char *application,
+ const uint8_t *key_handle, size_t key_handle_len)
{
fido_assert_t *assert = NULL;
+ /* generate an invalid signature on FIDO2 tokens */
+ const char *data = "";
+ uint8_t message[32];
int r = FIDO_ERR_INTERNAL;
+ if (sha256_mem(data, strlen(data), message, sizeof(message)) != 0) {
+ skdebug(__func__, "hash message failed");
+ goto out;
+ }
if ((assert = fido_assert_new()) == NULL) {
skdebug(__func__, "fido_assert_new failed");
goto out;
}
if ((r = fido_assert_set_clientdata_hash(assert, message,
- message_len)) != FIDO_OK) {
+ sizeof(message))) != FIDO_OK) {
skdebug(__func__, "fido_assert_set_clientdata_hash: %s",
fido_strerr(r));
goto out;
@@ -185,7 +358,7 @@ try_device(fido_dev_t *dev, const uint8_t *message, size_t message_len,
skdebug(__func__, "fido_assert_up: %s", fido_strerr(r));
goto out;
}
- r = fido_dev_get_assert(dev, assert, NULL);
+ r = fido_dev_get_assert(sk->dev, assert, NULL);
skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r));
if (r == FIDO_ERR_USER_PRESENCE_REQUIRED) {
/* U2F tokens may return this */
@@ -197,76 +370,122 @@ try_device(fido_dev_t *dev, const uint8_t *message, size_t message_len,
return r != FIDO_OK ? -1 : 0;
}
-/* Iterate over configured devices looking for a specific key handle */
-static fido_dev_t *
-find_device(const char *path, const uint8_t *message, size_t message_len,
+static struct sk_usbhid *
+sk_select_by_cred(const fido_dev_info_t *devlist, size_t ndevs,
const char *application, const uint8_t *key_handle, size_t key_handle_len)
{
- fido_dev_info_t *devlist = NULL;
- fido_dev_t *dev = NULL;
- size_t devlist_len = 0, i;
- int r;
+ struct sk_usbhid **skv, *sk;
+ size_t skvcnt, i;
- if (path != NULL) {
- if ((dev = fido_dev_new()) == NULL) {
- skdebug(__func__, "fido_dev_new failed");
- return NULL;
- }
- if ((r = fido_dev_open(dev, path)) != FIDO_OK) {
- skdebug(__func__, "fido_dev_open failed");
- fido_dev_free(&dev);
- return NULL;
+ if ((skv = sk_openv(devlist, ndevs, &skvcnt)) == NULL) {
+ skdebug(__func__, "sk_openv failed");
+ return NULL;
+ }
+ if (skvcnt == 1) {
+ sk = skv[0];
+ skv[0] = NULL;
+ goto out;
+ }
+ sk = NULL;
+ for (i = 0; i < skvcnt; i++) {
+ if (sk_try(skv[i], application, key_handle,
+ key_handle_len) == 0) {
+ sk = skv[i];
+ skv[i] = NULL;
+ skdebug(__func__, "found key in %s", sk->path);
+ break;
}
- return dev;
}
+ out:
+ sk_closev(skv, skvcnt);
+ return sk;
+}
- if ((devlist = fido_dev_info_new(MAX_FIDO_DEVICES)) == NULL) {
- skdebug(__func__, "fido_dev_info_new failed");
+static struct sk_usbhid *
+sk_select_by_touch(const fido_dev_info_t *devlist, size_t ndevs)
+{
+ struct sk_usbhid **skv, *sk;
+ struct timeval tv_start, tv_now, tv_delta;
+ size_t skvcnt, idx;
+ int touch, ms_remain;
+
+ if ((skv = sk_openv(devlist, ndevs, &skvcnt)) == NULL) {
+ skdebug(__func__, "sk_openv failed");
+ return NULL;
+ }
+ sk = NULL;
+ if (skvcnt < 2) {
+ if (skvcnt == 1) {
+ /* single candidate */
+ sk = skv[0];
+ skv[0] = NULL;
+ }
goto out;
}
- if ((r = fido_dev_info_manifest(devlist, MAX_FIDO_DEVICES,
- &devlist_len)) != FIDO_OK) {
- skdebug(__func__, "fido_dev_info_manifest: %s", fido_strerr(r));
+#ifndef HAVE_FIDO_DEV_GET_TOUCH_STATUS
+ skdebug(__func__, "libfido2 version does not support a feature needed for multiple tokens. Please upgrade to >=1.5.0");
+ goto out;
+#endif
+
+ if (sk_touch_begin(skv, skvcnt) == -1) {
+ skdebug(__func__, "sk_touch_begin failed");
goto out;
}
-
- skdebug(__func__, "found %zu device(s)", devlist_len);
-
- for (i = 0; i < devlist_len; i++) {
- const fido_dev_info_t *di = fido_dev_info_ptr(devlist, i);
-
- if (di == NULL) {
- skdebug(__func__, "fido_dev_info_ptr %zu failed", i);
- continue;
- }
- if ((path = fido_dev_info_path(di)) == NULL) {
- skdebug(__func__, "fido_dev_info_path %zu failed", i);
- continue;
- }
- skdebug(__func__, "trying device %zu: %s", i, path);
- if ((dev = fido_dev_new()) == NULL) {
- skdebug(__func__, "fido_dev_new failed");
- continue;
- }
- if ((r = fido_dev_open(dev, path)) != FIDO_OK) {
- skdebug(__func__, "fido_dev_open failed");
- fido_dev_free(&dev);
- continue;
+ monotime_tv(&tv_start);
+ do {
+ if (sk_touch_poll(skv, skvcnt, &touch, &idx) == -1) {
+ skdebug(__func__, "sk_touch_poll failed");
+ goto out;
}
- if (try_device(dev, message, message_len, application,
- key_handle, key_handle_len) == 0) {
- skdebug(__func__, "found key");
- break;
+ if (touch) {
+ sk = skv[idx];
+ skv[idx] = NULL;
+ goto out;
}
- fido_dev_close(dev);
- fido_dev_free(&dev);
- }
+ monotime_tv(&tv_now);
+ timersub(&tv_now, &tv_start, &tv_delta);
+ ms_remain = SELECT_MS - tv_delta.tv_sec * 1000 -
+ tv_delta.tv_usec / 1000;
+ } while (ms_remain >= FIDO_POLL_MS);
+ skdebug(__func__, "timeout");
+out:
+ sk_closev(skv, skvcnt);
+ return sk;
+}
- out:
- if (devlist != NULL)
- fido_dev_info_free(&devlist, MAX_FIDO_DEVICES);
+static struct sk_usbhid *
+sk_probe(const char *application, const uint8_t *key_handle,
+ size_t key_handle_len)
+{
+ struct sk_usbhid *sk;
+ fido_dev_info_t *devlist;
+ size_t ndevs;
+ int r;
- return dev;
+ if ((devlist = fido_dev_info_new(MAX_FIDO_DEVICES)) == NULL) {
+ skdebug(__func__, "fido_dev_info_new failed");
+ return NULL;
+ }
+ if ((r = fido_dev_info_manifest(devlist, MAX_FIDO_DEVICES,
+ &ndevs)) != FIDO_OK) {
+ skdebug(__func__, "fido_dev_info_manifest failed: %s",
+ fido_strerr(r));
+ fido_dev_info_free(&devlist, MAX_FIDO_DEVICES);
+ return NULL;
+ }
+ skdebug(__func__, "%zu device(s) detected", ndevs);
+ if (ndevs == 0) {
+ sk = NULL;
+ } else if (application != NULL && key_handle != NULL) {
+ skdebug(__func__, "selecting sk by cred");
+ sk = sk_select_by_cred(devlist, ndevs, application, key_handle,
+ key_handle_len);
+ } else {
+ skdebug(__func__, "selecting sk by touch");
+ sk = sk_select_by_touch(devlist, ndevs);
+ }
+ fido_dev_info_free(&devlist, MAX_FIDO_DEVICES);
+ return sk;
}
#ifdef WITH_OPENSSL
@@ -449,29 +668,29 @@ sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
struct sk_option **options, struct sk_enroll_response **enroll_response)
{
fido_cred_t *cred = NULL;
- fido_dev_t *dev = NULL;
const uint8_t *ptr;
- uint8_t user_id[32];
+ uint8_t user_id[32], chall_hash[32];
+ struct sk_usbhid *sk = NULL;
struct sk_enroll_response *response = NULL;
size_t len;
+ int credprot;
int cose_alg;
int ret = SSH_SK_ERR_GENERAL;
int r;
char *device = NULL;
-#ifdef SK_DEBUG
- fido_init(FIDO_DEBUG);
-#endif
+ fido_init(SSH_FIDO_INIT_ARG);
+
if (enroll_response == NULL) {
skdebug(__func__, "enroll_response == NULL");
goto out;
}
+ *enroll_response = NULL;
memset(user_id, 0, sizeof(user_id));
- if (check_enroll_options(options, &device,
- user_id, sizeof(user_id)) != 0)
+ if (check_enroll_options(options, &device, user_id,
+ sizeof(user_id)) != 0)
goto out; /* error already logged */
- *enroll_response = NULL;
switch(alg) {
#ifdef WITH_OPENSSL
case SSH_SK_ECDSA:
@@ -485,12 +704,15 @@ sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
skdebug(__func__, "unsupported key type %d", alg);
goto out;
}
- if (device == NULL && (device = pick_first_device()) == NULL) {
- ret = SSH_SK_ERR_DEVICE_NOT_FOUND;
- skdebug(__func__, "pick_first_device failed");
+ if (device != NULL)
+ sk = sk_open(device);
+ else
+ sk = sk_probe(NULL, NULL, 0);
+ if (sk == NULL) {
+ skdebug(__func__, "failed to find sk");
goto out;
}
- skdebug(__func__, "using device %s", device);
+ skdebug(__func__, "using device %s", sk->path);
if ((cred = fido_cred_new()) == NULL) {
skdebug(__func__, "fido_cred_new failed");
goto out;
@@ -499,8 +721,13 @@ sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
skdebug(__func__, "fido_cred_set_type: %s", fido_strerr(r));
goto out;
}
- if ((r = fido_cred_set_clientdata_hash(cred, challenge,
- challenge_len)) != FIDO_OK) {
+ if (sha256_mem(challenge, challenge_len,
+ chall_hash, sizeof(chall_hash)) != 0) {
+ skdebug(__func__, "hash challenge failed");
+ goto out;
+ }
+ if ((r = fido_cred_set_clientdata_hash(cred, chall_hash,
+ sizeof(chall_hash))) != FIDO_OK) {
skdebug(__func__, "fido_cred_set_clientdata_hash: %s",
fido_strerr(r));
goto out;
@@ -519,15 +746,34 @@ sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
skdebug(__func__, "fido_cred_set_rp: %s", fido_strerr(r));
goto out;
}
- if ((dev = fido_dev_new()) == NULL) {
- skdebug(__func__, "fido_dev_new failed");
- goto out;
- }
- if ((r = fido_dev_open(dev, device)) != FIDO_OK) {
- skdebug(__func__, "fido_dev_open: %s", fido_strerr(r));
+ if ((flags & (SSH_SK_RESIDENT_KEY|SSH_SK_USER_VERIFICATION_REQD)) != 0) {
+#if !defined(HAVE_FIDO_DEV_SUPPORTS_CRED_PROT) || \
+ !defined(HAVE_FIDO_CRED_SET_PROT)
+ skdebug(__func__, "libfido2 version does not support a feature required for this operation. Please upgrade to >=1.5.0");
+ ret = SSH_SK_ERR_UNSUPPORTED;
goto out;
+ credprot = 0; (void)credprot; /* avoid warning */
+#endif
+ if (!fido_dev_supports_cred_prot(sk->dev)) {
+ skdebug(__func__, "%s does not support credprot, "
+ "refusing to create unprotected "
+ "resident/verify-required key", sk->path);
+ ret = SSH_SK_ERR_UNSUPPORTED;
+ goto out;
+ }
+ if ((flags & SSH_SK_USER_VERIFICATION_REQD))
+ credprot = FIDO_CRED_PROT_UV_REQUIRED;
+ else
+ credprot = FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID;
+
+ if ((r = fido_cred_set_prot(cred, credprot)) != FIDO_OK) {
+ skdebug(__func__, "fido_cred_set_prot: %s",
+ fido_strerr(r));
+ ret = fidoerr_to_skerr(r);
+ goto out;
+ }
}
- if ((r = fido_dev_make_cred(dev, cred, pin)) != FIDO_OK) {
+ if ((r = fido_dev_make_cred(sk->dev, cred, pin)) != FIDO_OK) {
skdebug(__func__, "fido_dev_make_cred: %s", fido_strerr(r));
ret = fidoerr_to_skerr(r);
goto out;
@@ -574,7 +820,7 @@ sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
}
if ((ptr = fido_cred_x5c_ptr(cred)) != NULL) {
len = fido_cred_x5c_len(cred);
- debug3("%s: attestation cert len=%zu", __func__, len);
+ skdebug(__func__, "attestation cert len=%zu", len);
if ((response->attestation_cert = calloc(1, len)) == NULL) {
skdebug(__func__, "calloc attestation cert failed");
goto out;
@@ -582,6 +828,16 @@ sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
memcpy(response->attestation_cert, ptr, len);
response->attestation_cert_len = len;
}
+ if ((ptr = fido_cred_authdata_ptr(cred)) != NULL) {
+ len = fido_cred_authdata_len(cred);
+ skdebug(__func__, "authdata len=%zu", len);
+ if ((response->authdata = calloc(1, len)) == NULL) {
+ skdebug(__func__, "calloc authdata failed");
+ goto out;
+ }
+ memcpy(response->authdata, ptr, len);
+ response->authdata_len = len;
+ }
*enroll_response = response;
response = NULL;
ret = 0;
@@ -592,15 +848,11 @@ sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len,
free(response->key_handle);
free(response->signature);
free(response->attestation_cert);
+ free(response->authdata);
free(response);
}
- if (dev != NULL) {
- fido_dev_close(dev);
- fido_dev_free(&dev);
- }
- if (cred != NULL) {
- fido_cred_free(&cred);
- }
+ sk_close(sk);
+ fido_cred_free(&cred);
return ret;
}
@@ -714,26 +966,6 @@ check_sign_load_resident_options(struct sk_option **options, char **devicep)
return 0;
}
-/* Calculate SHA256(m) */
-static int
-sha256_mem(const void *m, size_t mlen, u_char *d, size_t dlen)
-{
-#ifdef WITH_OPENSSL
- u_int mdlen;
-#endif
-
- if (dlen != 32)
- return -1;
-#ifdef WITH_OPENSSL
- mdlen = dlen;
- if (!EVP_Digest(m, mlen, d, &mdlen, EVP_sha256(), NULL))
- return -1;
-#else
- SHA256Data(m, mlen, d);
-#endif
- return 0;
-}
-
int
sk_sign(uint32_t alg, const uint8_t *data, size_t datalen,
const char *application,
@@ -743,15 +975,13 @@ sk_sign(uint32_t alg, const uint8_t *data, size_t datalen,
{
fido_assert_t *assert = NULL;
char *device = NULL;
- fido_dev_t *dev = NULL;
+ struct sk_usbhid *sk = NULL;
struct sk_sign_response *response = NULL;
uint8_t message[32];
int ret = SSH_SK_ERR_GENERAL;
int r;
-#ifdef SK_DEBUG
- fido_init(FIDO_DEBUG);
-#endif
+ fido_init(SSH_FIDO_INIT_ARG);
if (sign_response == NULL) {
skdebug(__func__, "sign_response == NULL");
@@ -765,9 +995,14 @@ sk_sign(uint32_t alg, const uint8_t *data, size_t datalen,
skdebug(__func__, "hash message failed");
goto out;
}
- if ((dev = find_device(device, message, sizeof(message),
- application, key_handle, key_handle_len)) == NULL) {
- skdebug(__func__, "couldn't find device for key handle");
+ if (device != NULL)
+ sk = sk_open(device);
+ else if (pin != NULL || (flags & SSH_SK_USER_VERIFICATION_REQD))
+ sk = sk_probe(NULL, NULL, 0);
+ else
+ sk = sk_probe(application, key_handle, key_handle_len);
+ if (sk == NULL) {
+ skdebug(__func__, "failed to find sk");
goto out;
}
if ((assert = fido_assert_new()) == NULL) {
@@ -795,8 +1030,15 @@ sk_sign(uint32_t alg, const uint8_t *data, size_t datalen,
skdebug(__func__, "fido_assert_set_up: %s", fido_strerr(r));
goto out;
}
- if ((r = fido_dev_get_assert(dev, assert, NULL)) != FIDO_OK) {
+ if (pin == NULL && (flags & SSH_SK_USER_VERIFICATION_REQD) &&
+ (r = fido_assert_set_uv(assert, FIDO_OPT_TRUE)) != FIDO_OK) {
+ skdebug(__func__, "fido_assert_set_uv: %s", fido_strerr(r));
+ ret = FIDO_ERR_PIN_REQUIRED;
+ goto out;
+ }
+ if ((r = fido_dev_get_assert(sk->dev, assert, pin)) != FIDO_OK) {
skdebug(__func__, "fido_dev_get_assert: %s", fido_strerr(r));
+ ret = fidoerr_to_skerr(r);
goto out;
}
if ((response = calloc(1, sizeof(*response))) == NULL) {
@@ -820,22 +1062,16 @@ sk_sign(uint32_t alg, const uint8_t *data, size_t datalen,
free(response->sig_s);
free(response);
}
- if (dev != NULL) {
- fido_dev_close(dev);
- fido_dev_free(&dev);
- }
- if (assert != NULL) {
- fido_assert_free(&assert);
- }
+ sk_close(sk);
+ fido_assert_free(&assert);
return ret;
}
static int
-read_rks(const char *devpath, const char *pin,
+read_rks(struct sk_usbhid *sk, const char *pin,
struct sk_resident_key ***rksp, size_t *nrksp)
{
int ret = SSH_SK_ERR_GENERAL, r = -1;
- fido_dev_t *dev = NULL;
fido_credman_metadata_t *metadata = NULL;
fido_credman_rp_t *rp = NULL;
fido_credman_rk_t *rk = NULL;
@@ -843,30 +1079,25 @@ read_rks(const char *devpath, const char *pin,
const fido_cred_t *cred;
struct sk_resident_key *srk = NULL, **tmp;
- if ((dev = fido_dev_new()) == NULL) {
- skdebug(__func__, "fido_dev_new failed");
- return ret;
- }
- if ((r = fido_dev_open(dev, devpath)) != FIDO_OK) {
- skdebug(__func__, "fido_dev_open %s failed: %s",
- devpath, fido_strerr(r));
- fido_dev_free(&dev);
- return ret;
+ if (pin == NULL) {
+ skdebug(__func__, "no PIN specified");
+ ret = SSH_SK_ERR_PIN_REQUIRED;
+ goto out;
}
if ((metadata = fido_credman_metadata_new()) == NULL) {
skdebug(__func__, "alloc failed");
goto out;
}
- if ((r = fido_credman_get_dev_metadata(dev, metadata, pin)) != 0) {
+ if ((r = fido_credman_get_dev_metadata(sk->dev, metadata, pin)) != 0) {
if (r == FIDO_ERR_INVALID_COMMAND) {
skdebug(__func__, "device %s does not support "
- "resident keys", devpath);
+ "resident keys", sk->path);
ret = 0;
goto out;
}
skdebug(__func__, "get metadata for %s failed: %s",
- devpath, fido_strerr(r));
+ sk->path, fido_strerr(r));
ret = fidoerr_to_skerr(r);
goto out;
}
@@ -877,14 +1108,14 @@ read_rks(const char *devpath, const char *pin,
skdebug(__func__, "alloc rp failed");
goto out;
}
- if ((r = fido_credman_get_dev_rp(dev, rp, pin)) != 0) {
+ if ((r = fido_credman_get_dev_rp(sk->dev, rp, pin)) != 0) {
skdebug(__func__, "get RPs for %s failed: %s",
- devpath, fido_strerr(r));
+ sk->path, fido_strerr(r));
goto out;
}
nrp = fido_credman_rp_count(rp);
skdebug(__func__, "Device %s has resident keys for %zu RPs",
- devpath, nrp);
+ sk->path, nrp);
/* Iterate over RP IDs that have resident keys */
for (i = 0; i < nrp; i++) {
@@ -901,10 +1132,10 @@ read_rks(const char *devpath, const char *pin,
skdebug(__func__, "alloc rk failed");
goto out;
}
- if ((r = fido_credman_get_dev_rk(dev, fido_credman_rp_id(rp, i),
- rk, pin)) != 0) {
+ if ((r = fido_credman_get_dev_rk(sk->dev,
+ fido_credman_rp_id(rp, i), rk, pin)) != 0) {
skdebug(__func__, "get RKs for %s slot %zu failed: %s",
- devpath, i, fido_strerr(r));
+ sk->path, i, fido_strerr(r));
goto out;
}
nrk = fido_credman_rk_count(rk);
@@ -918,8 +1149,9 @@ read_rks(const char *devpath, const char *pin,
continue;
}
skdebug(__func__, "Device %s RP \"%s\" slot %zu: "
- "type %d", devpath, fido_credman_rp_id(rp, i), j,
- fido_cred_type(cred));
+ "type %d flags 0x%02x prot 0x%02x", sk->path,
+ fido_credman_rp_id(rp, i), j, fido_cred_type(cred),
+ fido_cred_flags(cred), fido_cred_prot(cred));
/* build response entry */
if ((srk = calloc(1, sizeof(*srk))) == NULL ||
@@ -932,8 +1164,7 @@ read_rks(const char *devpath, const char *pin,
}
srk->key.key_handle_len = fido_cred_id_len(cred);
- memcpy(srk->key.key_handle,
- fido_cred_id_ptr(cred),
+ memcpy(srk->key.key_handle, fido_cred_id_ptr(cred),
srk->key.key_handle_len);
switch (fido_cred_type(cred)) {
@@ -949,6 +1180,9 @@ read_rks(const char *devpath, const char *pin,
goto out; /* XXX free rk and continue */
}
+ if (fido_cred_prot(cred) == FIDO_CRED_PROT_UV_REQUIRED)
+ srk->flags |= SSH_SK_USER_VERIFICATION_REQD;
+
if ((r = pack_public_key(srk->alg, cred,
&srk->key)) != 0) {
skdebug(__func__, "pack public key failed");
@@ -976,8 +1210,6 @@ read_rks(const char *devpath, const char *pin,
}
fido_credman_rp_free(&rp);
fido_credman_rk_free(&rk);
- fido_dev_close(dev);
- fido_dev_free(&dev);
fido_credman_metadata_free(&metadata);
return ret;
}
@@ -987,50 +1219,31 @@ sk_load_resident_keys(const char *pin, struct sk_option **options,
struct sk_resident_key ***rksp, size_t *nrksp)
{
int ret = SSH_SK_ERR_GENERAL, r = -1;
- fido_dev_info_t *devlist = NULL;
- size_t i, ndev = 0, nrks = 0;
- const fido_dev_info_t *di;
+ size_t i, nrks = 0;
struct sk_resident_key **rks = NULL;
+ struct sk_usbhid *sk = NULL;
char *device = NULL;
+
*rksp = NULL;
*nrksp = 0;
+ fido_init(SSH_FIDO_INIT_ARG);
+
if (check_sign_load_resident_options(options, &device) != 0)
goto out; /* error already logged */
- if (device != NULL) {
- skdebug(__func__, "trying %s", device);
- if ((r = read_rks(device, pin, &rks, &nrks)) != 0) {
- skdebug(__func__, "read_rks failed for %s", device);
- ret = r;
- goto out;
- }
- } else {
- /* Try all devices */
- if ((devlist = fido_dev_info_new(MAX_FIDO_DEVICES)) == NULL) {
- skdebug(__func__, "fido_dev_info_new failed");
- goto out;
- }
- if ((r = fido_dev_info_manifest(devlist,
- MAX_FIDO_DEVICES, &ndev)) != FIDO_OK) {
- skdebug(__func__, "fido_dev_info_manifest failed: %s",
- fido_strerr(r));
- goto out;
- }
- for (i = 0; i < ndev; i++) {
- if ((di = fido_dev_info_ptr(devlist, i)) == NULL) {
- skdebug(__func__, "no dev info at %zu", i);
- continue;
- }
- skdebug(__func__, "trying %s", fido_dev_info_path(di));
- if ((r = read_rks(fido_dev_info_path(di), pin,
- &rks, &nrks)) != 0) {
- skdebug(__func__, "read_rks failed for %s",
- fido_dev_info_path(di));
- /* remember last error */
- ret = r;
- continue;
- }
- }
+ if (device != NULL)
+ sk = sk_open(device);
+ else
+ sk = sk_probe(NULL, NULL, 0);
+ if (sk == NULL) {
+ skdebug(__func__, "failed to find sk");
+ goto out;
+ }
+ skdebug(__func__, "trying %s", sk->path);
+ if ((r = read_rks(sk, pin, &rks, &nrks)) != 0) {
+ skdebug(__func__, "read_rks failed for %s", sk->path);
+ ret = r;
+ goto out;
}
/* success, unless we have no keys but a specific error */
if (nrks > 0 || ret == SSH_SK_ERR_GENERAL)
@@ -1040,7 +1253,7 @@ sk_load_resident_keys(const char *pin, struct sk_option **options,
rks = NULL;
nrks = 0;
out:
- free(device);
+ sk_close(sk);
for (i = 0; i < nrks; i++) {
free(rks[i]->application);
freezero(rks[i]->key.public_key, rks[i]->key.public_key_len);
@@ -1048,7 +1261,6 @@ sk_load_resident_keys(const char *pin, struct sk_option **options,
freezero(rks[i], sizeof(*rks[i]));
}
free(rks);
- fido_dev_info_free(&devlist, MAX_FIDO_DEVICES);
return ret;
}
diff --git a/sntrup4591761.c b/sntrup4591761.c
deleted file mode 100644
index 61fe2483f..000000000
--- a/sntrup4591761.c
+++ /dev/null
@@ -1,1083 +0,0 @@
-/* $OpenBSD: sntrup4591761.c,v 1.3 2019/01/30 19:51:15 markus Exp $ */
-
-/*
- * Public Domain, Authors:
- * - Daniel J. Bernstein
- * - Chitchanok Chuengsatiansup
- * - Tanja Lange
- * - Christine van Vredendaal
- */
-
-#include "includes.h"
-
-#include <string.h>
-#include "crypto_api.h"
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/int32_sort.h */
-#ifndef int32_sort_h
-#define int32_sort_h
-
-
-static void int32_sort(crypto_int32 *,int);
-
-#endif
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/int32_sort.c */
-/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
-
-
-static void minmax(crypto_int32 *x,crypto_int32 *y)
-{
- crypto_uint32 xi = *x;
- crypto_uint32 yi = *y;
- crypto_uint32 xy = xi ^ yi;
- crypto_uint32 c = yi - xi;
- c ^= xy & (c ^ yi);
- c >>= 31;
- c = -c;
- c &= xy;
- *x = xi ^ c;
- *y = yi ^ c;
-}
-
-static void int32_sort(crypto_int32 *x,int n)
-{
- int top,p,q,i;
-
- if (n < 2) return;
- top = 1;
- while (top < n - top) top += top;
-
- for (p = top;p > 0;p >>= 1) {
- for (i = 0;i < n - p;++i)
- if (!(i & p))
- minmax(x + i,x + i + p);
- for (q = top;q > p;q >>= 1)
- for (i = 0;i < n - q;++i)
- if (!(i & p))
- minmax(x + i + p,x + i + q);
- }
-}
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/small.h */
-#ifndef small_h
-#define small_h
-
-
-typedef crypto_int8 small;
-
-static void small_encode(unsigned char *,const small *);
-
-static void small_decode(small *,const unsigned char *);
-
-
-static void small_random(small *);
-
-static void small_random_weightw(small *);
-
-#endif
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/mod3.h */
-#ifndef mod3_h
-#define mod3_h
-
-
-/* -1 if x is nonzero, 0 otherwise */
-static inline int mod3_nonzero_mask(small x)
-{
- return -x*x;
-}
-
-/* input between -100000 and 100000 */
-/* output between -1 and 1 */
-static inline small mod3_freeze(crypto_int32 a)
-{
- a -= 3 * ((10923 * a) >> 15);
- a -= 3 * ((89478485 * a + 134217728) >> 28);
- return a;
-}
-
-static inline small mod3_minusproduct(small a,small b,small c)
-{
- crypto_int32 A = a;
- crypto_int32 B = b;
- crypto_int32 C = c;
- return mod3_freeze(A - B * C);
-}
-
-static inline small mod3_plusproduct(small a,small b,small c)
-{
- crypto_int32 A = a;
- crypto_int32 B = b;
- crypto_int32 C = c;
- return mod3_freeze(A + B * C);
-}
-
-static inline small mod3_product(small a,small b)
-{
- return a * b;
-}
-
-static inline small mod3_sum(small a,small b)
-{
- crypto_int32 A = a;
- crypto_int32 B = b;
- return mod3_freeze(A + B);
-}
-
-static inline small mod3_reciprocal(small a1)
-{
- return a1;
-}
-
-static inline small mod3_quotient(small num,small den)
-{
- return mod3_product(num,mod3_reciprocal(den));
-}
-
-#endif
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/modq.h */
-#ifndef modq_h
-#define modq_h
-
-
-typedef crypto_int16 modq;
-
-/* -1 if x is nonzero, 0 otherwise */
-static inline int modq_nonzero_mask(modq x)
-{
- crypto_int32 r = (crypto_uint16) x;
- r = -r;
- r >>= 30;
- return r;
-}
-
-/* input between -9000000 and 9000000 */
-/* output between -2295 and 2295 */
-static inline modq modq_freeze(crypto_int32 a)
-{
- a -= 4591 * ((228 * a) >> 20);
- a -= 4591 * ((58470 * a + 134217728) >> 28);
- return a;
-}
-
-static inline modq modq_minusproduct(modq a,modq b,modq c)
-{
- crypto_int32 A = a;
- crypto_int32 B = b;
- crypto_int32 C = c;
- return modq_freeze(A - B * C);
-}
-
-static inline modq modq_plusproduct(modq a,modq b,modq c)
-{
- crypto_int32 A = a;
- crypto_int32 B = b;
- crypto_int32 C = c;
- return modq_freeze(A + B * C);
-}
-
-static inline modq modq_product(modq a,modq b)
-{
- crypto_int32 A = a;
- crypto_int32 B = b;
- return modq_freeze(A * B);
-}
-
-static inline modq modq_square(modq a)
-{
- crypto_int32 A = a;
- return modq_freeze(A * A);
-}
-
-static inline modq modq_sum(modq a,modq b)
-{
- crypto_int32 A = a;
- crypto_int32 B = b;
- return modq_freeze(A + B);
-}
-
-static inline modq modq_reciprocal(modq a1)
-{
- modq a2 = modq_square(a1);
- modq a3 = modq_product(a2,a1);
- modq a4 = modq_square(a2);
- modq a8 = modq_square(a4);
- modq a16 = modq_square(a8);
- modq a32 = modq_square(a16);
- modq a35 = modq_product(a32,a3);
- modq a70 = modq_square(a35);
- modq a140 = modq_square(a70);
- modq a143 = modq_product(a140,a3);
- modq a286 = modq_square(a143);
- modq a572 = modq_square(a286);
- modq a1144 = modq_square(a572);
- modq a1147 = modq_product(a1144,a3);
- modq a2294 = modq_square(a1147);
- modq a4588 = modq_square(a2294);
- modq a4589 = modq_product(a4588,a1);
- return a4589;
-}
-
-static inline modq modq_quotient(modq num,modq den)
-{
- return modq_product(num,modq_reciprocal(den));
-}
-
-#endif
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/params.h */
-#ifndef params_h
-#define params_h
-
-#define q 4591
-/* XXX: also built into modq in various ways */
-
-#define qshift 2295
-#define p 761
-#define w 286
-
-#define rq_encode_len 1218
-#define small_encode_len 191
-
-#endif
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/r3.h */
-#ifndef r3_h
-#define r3_h
-
-
-static void r3_mult(small *,const small *,const small *);
-
-extern int r3_recip(small *,const small *);
-
-#endif
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq.h */
-#ifndef rq_h
-#define rq_h
-
-
-static void rq_encode(unsigned char *,const modq *);
-
-static void rq_decode(modq *,const unsigned char *);
-
-static void rq_encoderounded(unsigned char *,const modq *);
-
-static void rq_decoderounded(modq *,const unsigned char *);
-
-static void rq_round3(modq *,const modq *);
-
-static void rq_mult(modq *,const modq *,const small *);
-
-int rq_recip3(modq *,const small *);
-
-#endif
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/swap.h */
-#ifndef swap_h
-#define swap_h
-
-static void swap(void *,void *,int,int);
-
-#endif
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/dec.c */
-/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
-
-#ifdef KAT
-#endif
-
-
-int crypto_kem_sntrup4591761_dec(
- unsigned char *k,
- const unsigned char *cstr,
- const unsigned char *sk
-)
-{
- small f[p];
- modq h[p];
- small grecip[p];
- modq c[p];
- modq t[p];
- small t3[p];
- small r[p];
- modq hr[p];
- unsigned char rstr[small_encode_len];
- unsigned char hash[64];
- int i;
- int result = 0;
- int weight;
-
- small_decode(f,sk);
- small_decode(grecip,sk + small_encode_len);
- rq_decode(h,sk + 2 * small_encode_len);
-
- rq_decoderounded(c,cstr + 32);
-
- rq_mult(t,c,f);
- for (i = 0;i < p;++i) t3[i] = mod3_freeze(modq_freeze(3*t[i]));
-
- r3_mult(r,t3,grecip);
-
-#ifdef KAT
- {
- int j;
- printf("decrypt r:");
- for (j = 0;j < p;++j)
- if (r[j] == 1) printf(" +%d",j);
- else if (r[j] == -1) printf(" -%d",j);
- printf("\n");
- }
-#endif
-
- weight = 0;
- for (i = 0;i < p;++i) weight += (1 & r[i]);
- weight -= w;
- result |= modq_nonzero_mask(weight); /* XXX: puts limit on p */
-
- rq_mult(hr,h,r);
- rq_round3(hr,hr);
- for (i = 0;i < p;++i) result |= modq_nonzero_mask(hr[i] - c[i]);
-
- small_encode(rstr,r);
- crypto_hash_sha512(hash,rstr,sizeof rstr);
- result |= crypto_verify_32(hash,cstr);
-
- for (i = 0;i < 32;++i) k[i] = (hash[32 + i] & ~result);
- return result;
-}
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/enc.c */
-/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
-
-#ifdef KAT
-#endif
-
-
-int crypto_kem_sntrup4591761_enc(
- unsigned char *cstr,
- unsigned char *k,
- const unsigned char *pk
-)
-{
- small r[p];
- modq h[p];
- modq c[p];
- unsigned char rstr[small_encode_len];
- unsigned char hash[64];
-
- small_random_weightw(r);
-
-#ifdef KAT
- {
- int i;
- printf("encrypt r:");
- for (i = 0;i < p;++i)
- if (r[i] == 1) printf(" +%d",i);
- else if (r[i] == -1) printf(" -%d",i);
- printf("\n");
- }
-#endif
-
- small_encode(rstr,r);
- crypto_hash_sha512(hash,rstr,sizeof rstr);
-
- rq_decode(h,pk);
- rq_mult(c,h,r);
- rq_round3(c,c);
-
- memcpy(k,hash + 32,32);
- memcpy(cstr,hash,32);
- rq_encoderounded(cstr + 32,c);
-
- return 0;
-}
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/keypair.c */
-/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
-
-
-#if crypto_kem_sntrup4591761_PUBLICKEYBYTES != rq_encode_len
-#error "crypto_kem_sntrup4591761_PUBLICKEYBYTES must match rq_encode_len"
-#endif
-#if crypto_kem_sntrup4591761_SECRETKEYBYTES != rq_encode_len + 2 * small_encode_len
-#error "crypto_kem_sntrup4591761_SECRETKEYBYTES must match rq_encode_len + 2 * small_encode_len"
-#endif
-
-int crypto_kem_sntrup4591761_keypair(unsigned char *pk,unsigned char *sk)
-{
- small g[p];
- small grecip[p];
- small f[p];
- modq f3recip[p];
- modq h[p];
-
- do
- small_random(g);
- while (r3_recip(grecip,g) != 0);
-
- small_random_weightw(f);
- rq_recip3(f3recip,f);
-
- rq_mult(h,f3recip,g);
-
- rq_encode(pk,h);
- small_encode(sk,f);
- small_encode(sk + small_encode_len,grecip);
- memcpy(sk + 2 * small_encode_len,pk,rq_encode_len);
-
- return 0;
-}
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/r3_mult.c */
-/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
-
-
-static void r3_mult(small *h,const small *f,const small *g)
-{
- small fg[p + p - 1];
- small result;
- int i, j;
-
- for (i = 0;i < p;++i) {
- result = 0;
- for (j = 0;j <= i;++j)
- result = mod3_plusproduct(result,f[j],g[i - j]);
- fg[i] = result;
- }
- for (i = p;i < p + p - 1;++i) {
- result = 0;
- for (j = i - p + 1;j < p;++j)
- result = mod3_plusproduct(result,f[j],g[i - j]);
- fg[i] = result;
- }
-
- for (i = p + p - 2;i >= p;--i) {
- fg[i - p] = mod3_sum(fg[i - p],fg[i]);
- fg[i - p + 1] = mod3_sum(fg[i - p + 1],fg[i]);
- }
-
- for (i = 0;i < p;++i)
- h[i] = fg[i];
-}
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/r3_recip.c */
-/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
-
-
-/* caller must ensure that x-y does not overflow */
-static int smaller_mask_r3_recip(int x,int y)
-{
- return (x - y) >> 31;
-}
-
-static void vectormod3_product(small *z,int len,const small *x,const small c)
-{
- int i;
- for (i = 0;i < len;++i) z[i] = mod3_product(x[i],c);
-}
-
-static void vectormod3_minusproduct(small *z,int len,const small *x,const small *y,const small c)
-{
- int i;
- for (i = 0;i < len;++i) z[i] = mod3_minusproduct(x[i],y[i],c);
-}
-
-static void vectormod3_shift(small *z,int len)
-{
- int i;
- for (i = len - 1;i > 0;--i) z[i] = z[i - 1];
- z[0] = 0;
-}
-
-/*
-r = s^(-1) mod m, returning 0, if s is invertible mod m
-or returning -1 if s is not invertible mod m
-r,s are polys of degree <p
-m is x^p-x-1
-*/
-int r3_recip(small *r,const small *s)
-{
- const int loops = 2*p + 1;
- int loop;
- small f[p + 1];
- small g[p + 1];
- small u[2*p + 2];
- small v[2*p + 2];
- small c;
- int i;
- int d = p;
- int e = p;
- int swapmask;
-
- for (i = 2;i < p;++i) f[i] = 0;
- f[0] = -1;
- f[1] = -1;
- f[p] = 1;
- /* generalization: can initialize f to any polynomial m */
- /* requirements: m has degree exactly p, nonzero constant coefficient */
-
- for (i = 0;i < p;++i) g[i] = s[i];
- g[p] = 0;
-
- for (i = 0;i <= loops;++i) u[i] = 0;
-
- v[0] = 1;
- for (i = 1;i <= loops;++i) v[i] = 0;
-
- loop = 0;
- for (;;) {
- /* e == -1 or d + e + loop <= 2*p */
-
- /* f has degree p: i.e., f[p]!=0 */
- /* f[i]==0 for i < p-d */
-
- /* g has degree <=p (so it fits in p+1 coefficients) */
- /* g[i]==0 for i < p-e */
-
- /* u has degree <=loop (so it fits in loop+1 coefficients) */
- /* u[i]==0 for i < p-d */
- /* if invertible: u[i]==0 for i < loop-p (so can look at just p+1 coefficients) */
-
- /* v has degree <=loop (so it fits in loop+1 coefficients) */
- /* v[i]==0 for i < p-e */
- /* v[i]==0 for i < loop-p (so can look at just p+1 coefficients) */
-
- if (loop >= loops) break;
-
- c = mod3_quotient(g[p],f[p]);
-
- vectormod3_minusproduct(g,p + 1,g,f,c);
- vectormod3_shift(g,p + 1);
-
-#ifdef SIMPLER
- vectormod3_minusproduct(v,loops + 1,v,u,c);
- vectormod3_shift(v,loops + 1);
-#else
- if (loop < p) {
- vectormod3_minusproduct(v,loop + 1,v,u,c);
- vectormod3_shift(v,loop + 2);
- } else {
- vectormod3_minusproduct(v + loop - p,p + 1,v + loop - p,u + loop - p,c);
- vectormod3_shift(v + loop - p,p + 2);
- }
-#endif
-
- e -= 1;
-
- ++loop;
-
- swapmask = smaller_mask_r3_recip(e,d) & mod3_nonzero_mask(g[p]);
- swap(&e,&d,sizeof e,swapmask);
- swap(f,g,(p + 1) * sizeof(small),swapmask);
-
-#ifdef SIMPLER
- swap(u,v,(loops + 1) * sizeof(small),swapmask);
-#else
- if (loop < p) {
- swap(u,v,(loop + 1) * sizeof(small),swapmask);
- } else {
- swap(u + loop - p,v + loop - p,(p + 1) * sizeof(small),swapmask);
- }
-#endif
- }
-
- c = mod3_reciprocal(f[p]);
- vectormod3_product(r,p,u + p,c);
- return smaller_mask_r3_recip(0,d);
-}
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/randomsmall.c */
-/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
-
-
-static void small_random(small *g)
-{
- int i;
-
- for (i = 0;i < p;++i) {
- crypto_uint32 r = small_random32();
- g[i] = (small) (((1073741823 & r) * 3) >> 30) - 1;
- }
-}
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/randomweightw.c */
-/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
-
-
-static void small_random_weightw(small *f)
-{
- crypto_int32 r[p];
- int i;
-
- for (i = 0;i < p;++i) r[i] = small_random32();
- for (i = 0;i < w;++i) r[i] &= -2;
- for (i = w;i < p;++i) r[i] = (r[i] & -3) | 1;
- int32_sort(r,p);
- for (i = 0;i < p;++i) f[i] = ((small) (r[i] & 3)) - 1;
-}
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq.c */
-/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
-
-
-static void rq_encode(unsigned char *c,const modq *f)
-{
- crypto_int32 f0, f1, f2, f3, f4;
- int i;
-
- for (i = 0;i < p/5;++i) {
- f0 = *f++ + qshift;
- f1 = *f++ + qshift;
- f2 = *f++ + qshift;
- f3 = *f++ + qshift;
- f4 = *f++ + qshift;
- /* now want f0 + 6144*f1 + ... as a 64-bit integer */
- f1 *= 3;
- f2 *= 9;
- f3 *= 27;
- f4 *= 81;
- /* now want f0 + f1<<11 + f2<<22 + f3<<33 + f4<<44 */
- f0 += f1 << 11;
- *c++ = f0; f0 >>= 8;
- *c++ = f0; f0 >>= 8;
- f0 += f2 << 6;
- *c++ = f0; f0 >>= 8;
- *c++ = f0; f0 >>= 8;
- f0 += f3 << 1;
- *c++ = f0; f0 >>= 8;
- f0 += f4 << 4;
- *c++ = f0; f0 >>= 8;
- *c++ = f0; f0 >>= 8;
- *c++ = f0;
- }
- /* XXX: using p mod 5 = 1 */
- f0 = *f++ + qshift;
- *c++ = f0; f0 >>= 8;
- *c++ = f0;
-}
-
-static void rq_decode(modq *f,const unsigned char *c)
-{
- crypto_uint32 c0, c1, c2, c3, c4, c5, c6, c7;
- crypto_uint32 f0, f1, f2, f3, f4;
- int i;
-
- for (i = 0;i < p/5;++i) {
- c0 = *c++;
- c1 = *c++;
- c2 = *c++;
- c3 = *c++;
- c4 = *c++;
- c5 = *c++;
- c6 = *c++;
- c7 = *c++;
-
- /* f0 + f1*6144 + f2*6144^2 + f3*6144^3 + f4*6144^4 */
- /* = c0 + c1*256 + ... + c6*256^6 + c7*256^7 */
- /* with each f between 0 and 4590 */
-
- c6 += c7 << 8;
- /* c6 <= 23241 = floor(4591*6144^4/2^48) */
- /* f4 = (16/81)c6 + (1/1296)(c5+[0,1]) - [0,0.75] */
- /* claim: 2^19 f4 < x < 2^19(f4+1) */
- /* where x = 103564 c6 + 405(c5+1) */
- /* proof: x - 2^19 f4 = (76/81)c6 + (37/81)c5 + 405 - (32768/81)[0,1] + 2^19[0,0.75] */
- /* at least 405 - 32768/81 > 0 */
- /* at most (76/81)23241 + (37/81)255 + 405 + 2^19 0.75 < 2^19 */
- f4 = (103564*c6 + 405*(c5+1)) >> 19;
-
- c5 += c6 << 8;
- c5 -= (f4 * 81) << 4;
- c4 += c5 << 8;
-
- /* f0 + f1*6144 + f2*6144^2 + f3*6144^3 */
- /* = c0 + c1*256 + c2*256^2 + c3*256^3 + c4*256^4 */
- /* c4 <= 247914 = floor(4591*6144^3/2^32) */
- /* f3 = (1/54)(c4+[0,1]) - [0,0.75] */
- /* claim: 2^19 f3 < x < 2^19(f3+1) */
- /* where x = 9709(c4+2) */
- /* proof: x - 2^19 f3 = 19418 - (1/27)c4 - (262144/27)[0,1] + 2^19[0,0.75] */
- /* at least 19418 - 247914/27 - 262144/27 > 0 */
- /* at most 19418 + 2^19 0.75 < 2^19 */
- f3 = (9709*(c4+2)) >> 19;
-
- c4 -= (f3 * 27) << 1;
- c3 += c4 << 8;
- /* f0 + f1*6144 + f2*6144^2 */
- /* = c0 + c1*256 + c2*256^2 + c3*256^3 */
- /* c3 <= 10329 = floor(4591*6144^2/2^24) */
- /* f2 = (4/9)c3 + (1/576)c2 + (1/147456)c1 + (1/37748736)c0 - [0,0.75] */
- /* claim: 2^19 f2 < x < 2^19(f2+1) */
- /* where x = 233017 c3 + 910(c2+2) */
- /* proof: x - 2^19 f2 = 1820 + (1/9)c3 - (2/9)c2 - (32/9)c1 - (1/72)c0 + 2^19[0,0.75] */
- /* at least 1820 - (2/9)255 - (32/9)255 - (1/72)255 > 0 */
- /* at most 1820 + (1/9)10329 + 2^19 0.75 < 2^19 */
- f2 = (233017*c3 + 910*(c2+2)) >> 19;
-
- c2 += c3 << 8;
- c2 -= (f2 * 9) << 6;
- c1 += c2 << 8;
- /* f0 + f1*6144 */
- /* = c0 + c1*256 */
- /* c1 <= 110184 = floor(4591*6144/2^8) */
- /* f1 = (1/24)c1 + (1/6144)c0 - (1/6144)f0 */
- /* claim: 2^19 f1 < x < 2^19(f1+1) */
- /* where x = 21845(c1+2) + 85 c0 */
- /* proof: x - 2^19 f1 = 43690 - (1/3)c1 - (1/3)c0 + 2^19 [0,0.75] */
- /* at least 43690 - (1/3)110184 - (1/3)255 > 0 */
- /* at most 43690 + 2^19 0.75 < 2^19 */
- f1 = (21845*(c1+2) + 85*c0) >> 19;
-
- c1 -= (f1 * 3) << 3;
- c0 += c1 << 8;
- f0 = c0;
-
- *f++ = modq_freeze(f0 + q - qshift);
- *f++ = modq_freeze(f1 + q - qshift);
- *f++ = modq_freeze(f2 + q - qshift);
- *f++ = modq_freeze(f3 + q - qshift);
- *f++ = modq_freeze(f4 + q - qshift);
- }
-
- c0 = *c++;
- c1 = *c++;
- c0 += c1 << 8;
- *f++ = modq_freeze(c0 + q - qshift);
-}
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_mult.c */
-/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
-
-
-static void rq_mult(modq *h,const modq *f,const small *g)
-{
- modq fg[p + p - 1];
- modq result;
- int i, j;
-
- for (i = 0;i < p;++i) {
- result = 0;
- for (j = 0;j <= i;++j)
- result = modq_plusproduct(result,f[j],g[i - j]);
- fg[i] = result;
- }
- for (i = p;i < p + p - 1;++i) {
- result = 0;
- for (j = i - p + 1;j < p;++j)
- result = modq_plusproduct(result,f[j],g[i - j]);
- fg[i] = result;
- }
-
- for (i = p + p - 2;i >= p;--i) {
- fg[i - p] = modq_sum(fg[i - p],fg[i]);
- fg[i - p + 1] = modq_sum(fg[i - p + 1],fg[i]);
- }
-
- for (i = 0;i < p;++i)
- h[i] = fg[i];
-}
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_recip3.c */
-/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
-
-
-/* caller must ensure that x-y does not overflow */
-static int smaller_mask_rq_recip3(int x,int y)
-{
- return (x - y) >> 31;
-}
-
-static void vectormodq_product(modq *z,int len,const modq *x,const modq c)
-{
- int i;
- for (i = 0;i < len;++i) z[i] = modq_product(x[i],c);
-}
-
-static void vectormodq_minusproduct(modq *z,int len,const modq *x,const modq *y,const modq c)
-{
- int i;
- for (i = 0;i < len;++i) z[i] = modq_minusproduct(x[i],y[i],c);
-}
-
-static void vectormodq_shift(modq *z,int len)
-{
- int i;
- for (i = len - 1;i > 0;--i) z[i] = z[i - 1];
- z[0] = 0;
-}
-
-/*
-r = (3s)^(-1) mod m, returning 0, if s is invertible mod m
-or returning -1 if s is not invertible mod m
-r,s are polys of degree <p
-m is x^p-x-1
-*/
-int rq_recip3(modq *r,const small *s)
-{
- const int loops = 2*p + 1;
- int loop;
- modq f[p + 1];
- modq g[p + 1];
- modq u[2*p + 2];
- modq v[2*p + 2];
- modq c;
- int i;
- int d = p;
- int e = p;
- int swapmask;
-
- for (i = 2;i < p;++i) f[i] = 0;
- f[0] = -1;
- f[1] = -1;
- f[p] = 1;
- /* generalization: can initialize f to any polynomial m */
- /* requirements: m has degree exactly p, nonzero constant coefficient */
-
- for (i = 0;i < p;++i) g[i] = 3 * s[i];
- g[p] = 0;
-
- for (i = 0;i <= loops;++i) u[i] = 0;
-
- v[0] = 1;
- for (i = 1;i <= loops;++i) v[i] = 0;
-
- loop = 0;
- for (;;) {
- /* e == -1 or d + e + loop <= 2*p */
-
- /* f has degree p: i.e., f[p]!=0 */
- /* f[i]==0 for i < p-d */
-
- /* g has degree <=p (so it fits in p+1 coefficients) */
- /* g[i]==0 for i < p-e */
-
- /* u has degree <=loop (so it fits in loop+1 coefficients) */
- /* u[i]==0 for i < p-d */
- /* if invertible: u[i]==0 for i < loop-p (so can look at just p+1 coefficients) */
-
- /* v has degree <=loop (so it fits in loop+1 coefficients) */
- /* v[i]==0 for i < p-e */
- /* v[i]==0 for i < loop-p (so can look at just p+1 coefficients) */
-
- if (loop >= loops) break;
-
- c = modq_quotient(g[p],f[p]);
-
- vectormodq_minusproduct(g,p + 1,g,f,c);
- vectormodq_shift(g,p + 1);
-
-#ifdef SIMPLER
- vectormodq_minusproduct(v,loops + 1,v,u,c);
- vectormodq_shift(v,loops + 1);
-#else
- if (loop < p) {
- vectormodq_minusproduct(v,loop + 1,v,u,c);
- vectormodq_shift(v,loop + 2);
- } else {
- vectormodq_minusproduct(v + loop - p,p + 1,v + loop - p,u + loop - p,c);
- vectormodq_shift(v + loop - p,p + 2);
- }
-#endif
-
- e -= 1;
-
- ++loop;
-
- swapmask = smaller_mask_rq_recip3(e,d) & modq_nonzero_mask(g[p]);
- swap(&e,&d,sizeof e,swapmask);
- swap(f,g,(p + 1) * sizeof(modq),swapmask);
-
-#ifdef SIMPLER
- swap(u,v,(loops + 1) * sizeof(modq),swapmask);
-#else
- if (loop < p) {
- swap(u,v,(loop + 1) * sizeof(modq),swapmask);
- } else {
- swap(u + loop - p,v + loop - p,(p + 1) * sizeof(modq),swapmask);
- }
-#endif
- }
-
- c = modq_reciprocal(f[p]);
- vectormodq_product(r,p,u + p,c);
- return smaller_mask_rq_recip3(0,d);
-}
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_round3.c */
-/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
-
-
-static void rq_round3(modq *h,const modq *f)
-{
- int i;
-
- for (i = 0;i < p;++i)
- h[i] = ((21846 * (f[i] + 2295) + 32768) >> 16) * 3 - 2295;
-}
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_rounded.c */
-/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
-
-
-static void rq_encoderounded(unsigned char *c,const modq *f)
-{
- crypto_int32 f0, f1, f2;
- int i;
-
- for (i = 0;i < p/3;++i) {
- f0 = *f++ + qshift;
- f1 = *f++ + qshift;
- f2 = *f++ + qshift;
- f0 = (21846 * f0) >> 16;
- f1 = (21846 * f1) >> 16;
- f2 = (21846 * f2) >> 16;
- /* now want f0 + f1*1536 + f2*1536^2 as a 32-bit integer */
- f2 *= 3;
- f1 += f2 << 9;
- f1 *= 3;
- f0 += f1 << 9;
- *c++ = f0; f0 >>= 8;
- *c++ = f0; f0 >>= 8;
- *c++ = f0; f0 >>= 8;
- *c++ = f0;
- }
- /* XXX: using p mod 3 = 2 */
- f0 = *f++ + qshift;
- f1 = *f++ + qshift;
- f0 = (21846 * f0) >> 16;
- f1 = (21846 * f1) >> 16;
- f1 *= 3;
- f0 += f1 << 9;
- *c++ = f0; f0 >>= 8;
- *c++ = f0; f0 >>= 8;
- *c++ = f0;
-}
-
-static void rq_decoderounded(modq *f,const unsigned char *c)
-{
- crypto_uint32 c0, c1, c2, c3;
- crypto_uint32 f0, f1, f2;
- int i;
-
- for (i = 0;i < p/3;++i) {
- c0 = *c++;
- c1 = *c++;
- c2 = *c++;
- c3 = *c++;
-
- /* f0 + f1*1536 + f2*1536^2 */
- /* = c0 + c1*256 + c2*256^2 + c3*256^3 */
- /* with each f between 0 and 1530 */
-
- /* f2 = (64/9)c3 + (1/36)c2 + (1/9216)c1 + (1/2359296)c0 - [0,0.99675] */
- /* claim: 2^21 f2 < x < 2^21(f2+1) */
- /* where x = 14913081*c3 + 58254*c2 + 228*(c1+2) */
- /* proof: x - 2^21 f2 = 456 - (8/9)c0 + (4/9)c1 - (2/9)c2 + (1/9)c3 + 2^21 [0,0.99675] */
- /* at least 456 - (8/9)255 - (2/9)255 > 0 */
- /* at most 456 + (4/9)255 + (1/9)255 + 2^21 0.99675 < 2^21 */
- f2 = (14913081*c3 + 58254*c2 + 228*(c1+2)) >> 21;
-
- c2 += c3 << 8;
- c2 -= (f2 * 9) << 2;
- /* f0 + f1*1536 */
- /* = c0 + c1*256 + c2*256^2 */
- /* c2 <= 35 = floor((1530+1530*1536)/256^2) */
- /* f1 = (128/3)c2 + (1/6)c1 + (1/1536)c0 - (1/1536)f0 */
- /* claim: 2^21 f1 < x < 2^21(f1+1) */
- /* where x = 89478485*c2 + 349525*c1 + 1365*(c0+1) */
- /* proof: x - 2^21 f1 = 1365 - (1/3)c2 - (1/3)c1 - (1/3)c0 + (4096/3)f0 */
- /* at least 1365 - (1/3)35 - (1/3)255 - (1/3)255 > 0 */
- /* at most 1365 + (4096/3)1530 < 2^21 */
- f1 = (89478485*c2 + 349525*c1 + 1365*(c0+1)) >> 21;
-
- c1 += c2 << 8;
- c1 -= (f1 * 3) << 1;
-
- c0 += c1 << 8;
- f0 = c0;
-
- *f++ = modq_freeze(f0 * 3 + q - qshift);
- *f++ = modq_freeze(f1 * 3 + q - qshift);
- *f++ = modq_freeze(f2 * 3 + q - qshift);
- }
-
- c0 = *c++;
- c1 = *c++;
- c2 = *c++;
-
- f1 = (89478485*c2 + 349525*c1 + 1365*(c0+1)) >> 21;
-
- c1 += c2 << 8;
- c1 -= (f1 * 3) << 1;
-
- c0 += c1 << 8;
- f0 = c0;
-
- *f++ = modq_freeze(f0 * 3 + q - qshift);
- *f++ = modq_freeze(f1 * 3 + q - qshift);
-}
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/small.c */
-/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
-
-
-/* XXX: these functions rely on p mod 4 = 1 */
-
-/* all coefficients in -1, 0, 1 */
-static void small_encode(unsigned char *c,const small *f)
-{
- small c0;
- int i;
-
- for (i = 0;i < p/4;++i) {
- c0 = *f++ + 1;
- c0 += (*f++ + 1) << 2;
- c0 += (*f++ + 1) << 4;
- c0 += (*f++ + 1) << 6;
- *c++ = c0;
- }
- c0 = *f++ + 1;
- *c++ = c0;
-}
-
-static void small_decode(small *f,const unsigned char *c)
-{
- unsigned char c0;
- int i;
-
- for (i = 0;i < p/4;++i) {
- c0 = *c++;
- *f++ = ((small) (c0 & 3)) - 1; c0 >>= 2;
- *f++ = ((small) (c0 & 3)) - 1; c0 >>= 2;
- *f++ = ((small) (c0 & 3)) - 1; c0 >>= 2;
- *f++ = ((small) (c0 & 3)) - 1;
- }
- c0 = *c++;
- *f++ = ((small) (c0 & 3)) - 1;
-}
-
-/* from libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/swap.c */
-/* See https://ntruprime.cr.yp.to/software.html for detailed documentation. */
-
-
-static void swap(void *x,void *y,int bytes,int mask)
-{
- int i;
- char xi, yi, c, t;
-
- c = mask;
-
- for (i = 0;i < bytes;++i) {
- xi = i[(char *) x];
- yi = i[(char *) y];
- t = c & (xi ^ yi);
- xi ^= t;
- yi ^= t;
- i[(char *) x] = xi;
- i[(char *) y] = yi;
- }
-}
-
diff --git a/sntrup4591761.sh b/sntrup4591761.sh
deleted file mode 100644
index e684c3329..000000000
--- a/sntrup4591761.sh
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/bin/sh
-# $OpenBSD: sntrup4591761.sh,v 1.3 2019/01/30 19:51:15 markus Exp $
-# Placed in the Public Domain.
-#
-AUTHOR="libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/implementors"
-FILES="
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/int32_sort.h
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/int32_sort.c
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/small.h
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/mod3.h
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/modq.h
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/params.h
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/r3.h
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq.h
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/swap.h
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/dec.c
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/enc.c
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/keypair.c
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/r3_mult.c
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/r3_recip.c
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/randomsmall.c
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/randomweightw.c
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq.c
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_mult.c
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_recip3.c
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_round3.c
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/rq_rounded.c
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/small.c
- libpqcrypto-20180314/crypto_kem/sntrup4591761/ref/swap.c
-"
-###
-
-set -e
-cd $1
-echo -n '/* $'
-echo 'OpenBSD: $ */'
-echo
-echo '/*'
-echo ' * Public Domain, Authors:'
-sed -e '/Alphabetical order:/d' -e 's/^/ * - /' < $AUTHOR
-echo ' */'
-echo
-echo '#include <string.h>'
-echo '#include "crypto_api.h"'
-echo
-for i in $FILES; do
- echo "/* from $i */"
- b=$(basename $i .c)
- grep \
- -v '#include' $i | \
- grep -v "extern crypto_int32 small_random32" |
- sed -e "s/crypto_kem_/crypto_kem_sntrup4591761_/g" \
- -e "s/smaller_mask/smaller_mask_${b}/g" \
- -e "s/^extern void /static void /" \
- -e "s/^void /static void /"
- echo
-done
diff --git a/sntrup761.c b/sntrup761.c
new file mode 100644
index 000000000..c63e600fb
--- /dev/null
+++ b/sntrup761.c
@@ -0,0 +1,1273 @@
+/* $OpenBSD: sntrup761.c,v 1.5 2021/01/08 02:33:13 dtucker Exp $ */
+
+/*
+ * Public Domain, Authors:
+ * - Daniel J. Bernstein
+ * - Chitchanok Chuengsatiansup
+ * - Tanja Lange
+ * - Christine van Vredendaal
+ */
+
+#include "includes.h"
+
+#ifdef USE_SNTRUP761X25519
+
+#include <string.h>
+#include "crypto_api.h"
+
+#define int8 crypto_int8
+#define uint8 crypto_uint8
+#define int16 crypto_int16
+#define uint16 crypto_uint16
+#define int32 crypto_int32
+#define uint32 crypto_uint32
+#define int64 crypto_int64
+#define uint64 crypto_uint64
+
+/* from supercop-20201130/crypto_sort/int32/portable4/int32_minmax.inc */
+#define int32_MINMAX(a,b) \
+do { \
+ int64_t ab = (int64_t)b ^ (int64_t)a; \
+ int64_t c = (int64_t)b - (int64_t)a; \
+ c ^= ab & (c ^ b); \
+ c >>= 31; \
+ c &= ab; \
+ a ^= c; \
+ b ^= c; \
+} while(0)
+
+/* from supercop-20201130/crypto_sort/int32/portable4/sort.c */
+
+
+static void crypto_sort_int32(void *array,long long n)
+{
+ long long top,p,q,r,i,j;
+ int32 *x = array;
+
+ if (n < 2) return;
+ top = 1;
+ while (top < n - top) top += top;
+
+ for (p = top;p >= 1;p >>= 1) {
+ i = 0;
+ while (i + 2 * p <= n) {
+ for (j = i;j < i + p;++j)
+ int32_MINMAX(x[j],x[j+p]);
+ i += 2 * p;
+ }
+ for (j = i;j < n - p;++j)
+ int32_MINMAX(x[j],x[j+p]);
+
+ i = 0;
+ j = 0;
+ for (q = top;q > p;q >>= 1) {
+ if (j != i) for (;;) {
+ if (j == n - q) goto done;
+ int32 a = x[j + p];
+ for (r = q;r > p;r >>= 1)
+ int32_MINMAX(a,x[j + r]);
+ x[j + p] = a;
+ ++j;
+ if (j == i + p) {
+ i += 2 * p;
+ break;
+ }
+ }
+ while (i + p <= n - q) {
+ for (j = i;j < i + p;++j) {
+ int32 a = x[j + p];
+ for (r = q;r > p;r >>= 1)
+ int32_MINMAX(a,x[j+r]);
+ x[j + p] = a;
+ }
+ i += 2 * p;
+ }
+ /* now i + p > n - q */
+ j = i;
+ while (j < n - q) {
+ int32 a = x[j + p];
+ for (r = q;r > p;r >>= 1)
+ int32_MINMAX(a,x[j+r]);
+ x[j + p] = a;
+ ++j;
+ }
+
+ done: ;
+ }
+ }
+}
+
+/* from supercop-20201130/crypto_sort/uint32/useint32/sort.c */
+
+/* can save time by vectorizing xor loops */
+/* can save time by integrating xor loops with int32_sort */
+
+static void crypto_sort_uint32(void *array,long long n)
+{
+ crypto_uint32 *x = array;
+ long long j;
+ for (j = 0;j < n;++j) x[j] ^= 0x80000000;
+ crypto_sort_int32(array,n);
+ for (j = 0;j < n;++j) x[j] ^= 0x80000000;
+}
+
+/* from supercop-20201130/crypto_kem/sntrup761/ref/uint32.c */
+
+/*
+CPU division instruction typically takes time depending on x.
+This software is designed to take time independent of x.
+Time still varies depending on m; user must ensure that m is constant.
+Time also varies on CPUs where multiplication is variable-time.
+There could be more CPU issues.
+There could also be compiler issues.
+*/
+
+static void uint32_divmod_uint14(uint32 *q,uint16 *r,uint32 x,uint16 m)
+{
+ uint32 v = 0x80000000;
+ uint32 qpart;
+ uint32 mask;
+
+ v /= m;
+
+ /* caller guarantees m > 0 */
+ /* caller guarantees m < 16384 */
+ /* vm <= 2^31 <= vm+m-1 */
+ /* xvm <= 2^31 x <= xvm+x(m-1) */
+
+ *q = 0;
+
+ qpart = (x*(uint64)v)>>31;
+ /* 2^31 qpart <= xv <= 2^31 qpart + 2^31-1 */
+ /* 2^31 qpart m <= xvm <= 2^31 qpart m + (2^31-1)m */
+ /* 2^31 qpart m <= 2^31 x <= 2^31 qpart m + (2^31-1)m + x(m-1) */
+ /* 0 <= 2^31 newx <= (2^31-1)m + x(m-1) */
+ /* 0 <= newx <= (1-1/2^31)m + x(m-1)/2^31 */
+ /* 0 <= newx <= (1-1/2^31)(2^14-1) + (2^32-1)((2^14-1)-1)/2^31 */
+
+ x -= qpart*m; *q += qpart;
+ /* x <= 49146 */
+
+ qpart = (x*(uint64)v)>>31;
+ /* 0 <= newx <= (1-1/2^31)m + x(m-1)/2^31 */
+ /* 0 <= newx <= m + 49146(2^14-1)/2^31 */
+ /* 0 <= newx <= m + 0.4 */
+ /* 0 <= newx <= m */
+
+ x -= qpart*m; *q += qpart;
+ /* x <= m */
+
+ x -= m; *q += 1;
+ mask = -(x>>31);
+ x += mask&(uint32)m; *q += mask;
+ /* x < m */
+
+ *r = x;
+}
+
+
+static uint16 uint32_mod_uint14(uint32 x,uint16 m)
+{
+ uint32 q;
+ uint16 r;
+ uint32_divmod_uint14(&q,&r,x,m);
+ return r;
+}
+
+/* from supercop-20201130/crypto_kem/sntrup761/ref/int32.c */
+
+static void int32_divmod_uint14(int32 *q,uint16 *r,int32 x,uint16 m)
+{
+ uint32 uq,uq2;
+ uint16 ur,ur2;
+ uint32 mask;
+
+ uint32_divmod_uint14(&uq,&ur,0x80000000+(uint32)x,m);
+ uint32_divmod_uint14(&uq2,&ur2,0x80000000,m);
+ ur -= ur2; uq -= uq2;
+ mask = -(uint32)(ur>>15);
+ ur += mask&m; uq += mask;
+ *r = ur; *q = uq;
+}
+
+
+static uint16 int32_mod_uint14(int32 x,uint16 m)
+{
+ int32 q;
+ uint16 r;
+ int32_divmod_uint14(&q,&r,x,m);
+ return r;
+}
+
+/* from supercop-20201130/crypto_kem/sntrup761/ref/paramsmenu.h */
+/* pick one of these three: */
+#define SIZE761
+#undef SIZE653
+#undef SIZE857
+
+/* pick one of these two: */
+#define SNTRUP /* Streamlined NTRU Prime */
+#undef LPR /* NTRU LPRime */
+
+/* from supercop-20201130/crypto_kem/sntrup761/ref/params.h */
+#ifndef params_H
+#define params_H
+
+/* menu of parameter choices: */
+
+
+/* what the menu means: */
+
+#if defined(SIZE761)
+#define p 761
+#define q 4591
+#define Rounded_bytes 1007
+#ifndef LPR
+#define Rq_bytes 1158
+#define w 286
+#else
+#define w 250
+#define tau0 2156
+#define tau1 114
+#define tau2 2007
+#define tau3 287
+#endif
+
+#elif defined(SIZE653)
+#define p 653
+#define q 4621
+#define Rounded_bytes 865
+#ifndef LPR
+#define Rq_bytes 994
+#define w 288
+#else
+#define w 252
+#define tau0 2175
+#define tau1 113
+#define tau2 2031
+#define tau3 290
+#endif
+
+#elif defined(SIZE857)
+#define p 857
+#define q 5167
+#define Rounded_bytes 1152
+#ifndef LPR
+#define Rq_bytes 1322
+#define w 322
+#else
+#define w 281
+#define tau0 2433
+#define tau1 101
+#define tau2 2265
+#define tau3 324
+#endif
+
+#else
+#error "no parameter set defined"
+#endif
+
+#ifdef LPR
+#define I 256
+#endif
+
+#endif
+
+/* from supercop-20201130/crypto_kem/sntrup761/ref/Decode.h */
+#ifndef Decode_H
+#define Decode_H
+
+
+/* Decode(R,s,M,len) */
+/* assumes 0 < M[i] < 16384 */
+/* produces 0 <= R[i] < M[i] */
+
+#endif
+
+/* from supercop-20201130/crypto_kem/sntrup761/ref/Decode.c */
+
+static void Decode(uint16 *out,const unsigned char *S,const uint16 *M,long long len)
+{
+ if (len == 1) {
+ if (M[0] == 1)
+ *out = 0;
+ else if (M[0] <= 256)
+ *out = uint32_mod_uint14(S[0],M[0]);
+ else
+ *out = uint32_mod_uint14(S[0]+(((uint16)S[1])<<8),M[0]);
+ }
+ if (len > 1) {
+ uint16 R2[(len+1)/2];
+ uint16 M2[(len+1)/2];
+ uint16 bottomr[len/2];
+ uint32 bottomt[len/2];
+ long long i;
+ for (i = 0;i < len-1;i += 2) {
+ uint32 m = M[i]*(uint32) M[i+1];
+ if (m > 256*16383) {
+ bottomt[i/2] = 256*256;
+ bottomr[i/2] = S[0]+256*S[1];
+ S += 2;
+ M2[i/2] = (((m+255)>>8)+255)>>8;
+ } else if (m >= 16384) {
+ bottomt[i/2] = 256;
+ bottomr[i/2] = S[0];
+ S += 1;
+ M2[i/2] = (m+255)>>8;
+ } else {
+ bottomt[i/2] = 1;
+ bottomr[i/2] = 0;
+ M2[i/2] = m;
+ }
+ }
+ if (i < len)
+ M2[i/2] = M[i];
+ Decode(R2,S,M2,(len+1)/2);
+ for (i = 0;i < len-1;i += 2) {
+ uint32 r = bottomr[i/2];
+ uint32 r1;
+ uint16 r0;
+ r += bottomt[i/2]*R2[i/2];
+ uint32_divmod_uint14(&r1,&r0,r,M[i]);
+ r1 = uint32_mod_uint14(r1,M[i+1]); /* only needed for invalid inputs */
+ *out++ = r0;
+ *out++ = r1;
+ }
+ if (i < len)
+ *out++ = R2[i/2];
+ }
+}
+
+/* from supercop-20201130/crypto_kem/sntrup761/ref/Encode.h */
+#ifndef Encode_H
+#define Encode_H
+
+
+/* Encode(s,R,M,len) */
+/* assumes 0 <= R[i] < M[i] < 16384 */
+
+#endif
+
+/* from supercop-20201130/crypto_kem/sntrup761/ref/Encode.c */
+
+/* 0 <= R[i] < M[i] < 16384 */
+static void Encode(unsigned char *out,const uint16 *R,const uint16 *M,long long len)
+{
+ if (len == 1) {
+ uint16 r = R[0];
+ uint16 m = M[0];
+ while (m > 1) {
+ *out++ = r;
+ r >>= 8;
+ m = (m+255)>>8;
+ }
+ }
+ if (len > 1) {
+ uint16 R2[(len+1)/2];
+ uint16 M2[(len+1)/2];
+ long long i;
+ for (i = 0;i < len-1;i += 2) {
+ uint32 m0 = M[i];
+ uint32 r = R[i]+R[i+1]*m0;
+ uint32 m = M[i+1]*m0;
+ while (m >= 16384) {
+ *out++ = r;
+ r >>= 8;
+ m = (m+255)>>8;
+ }
+ R2[i/2] = r;
+ M2[i/2] = m;
+ }
+ if (i < len) {
+ R2[i/2] = R[i];
+ M2[i/2] = M[i];
+ }
+ Encode(out,R2,M2,(len+1)/2);
+ }
+}
+
+/* from supercop-20201130/crypto_kem/sntrup761/ref/kem.c */
+
+#ifdef LPR
+#endif
+
+
+/* ----- masks */
+
+#ifndef LPR
+
+/* return -1 if x!=0; else return 0 */
+static int int16_nonzero_mask(int16 x)
+{
+ uint16 u = x; /* 0, else 1...65535 */
+ uint32 v = u; /* 0, else 1...65535 */
+ v = -v; /* 0, else 2^32-65535...2^32-1 */
+ v >>= 31; /* 0, else 1 */
+ return -v; /* 0, else -1 */
+}
+
+#endif
+
+/* return -1 if x<0; otherwise return 0 */
+static int int16_negative_mask(int16 x)
+{
+ uint16 u = x;
+ u >>= 15;
+ return -(int) u;
+ /* alternative with gcc -fwrapv: */
+ /* x>>15 compiles to CPU's arithmetic right shift */
+}
+
+/* ----- arithmetic mod 3 */
+
+typedef int8 small;
+
+/* F3 is always represented as -1,0,1 */
+/* so ZZ_fromF3 is a no-op */
+
+/* x must not be close to top int16 */
+static small F3_freeze(int16 x)
+{
+ return int32_mod_uint14(x+1,3)-1;
+}
+
+/* ----- arithmetic mod q */
+
+#define q12 ((q-1)/2)
+typedef int16 Fq;
+/* always represented as -q12...q12 */
+/* so ZZ_fromFq is a no-op */
+
+/* x must not be close to top int32 */
+static Fq Fq_freeze(int32 x)
+{
+ return int32_mod_uint14(x+q12,q)-q12;
+}
+
+#ifndef LPR
+
+static Fq Fq_recip(Fq a1)
+{
+ int i = 1;
+ Fq ai = a1;
+
+ while (i < q-2) {
+ ai = Fq_freeze(a1*(int32)ai);
+ i += 1;
+ }
+ return ai;
+}
+
+#endif
+
+/* ----- Top and Right */
+
+#ifdef LPR
+#define tau 16
+
+static int8 Top(Fq C)
+{
+ return (tau1*(int32)(C+tau0)+16384)>>15;
+}
+
+static Fq Right(int8 T)
+{
+ return Fq_freeze(tau3*(int32)T-tau2);
+}
+#endif
+
+/* ----- small polynomials */
+
+#ifndef LPR
+
+/* 0 if Weightw_is(r), else -1 */
+static int Weightw_mask(small *r)
+{
+ int weight = 0;
+ int i;
+
+ for (i = 0;i < p;++i) weight += r[i]&1;
+ return int16_nonzero_mask(weight-w);
+}
+
+/* R3_fromR(R_fromRq(r)) */
+static void R3_fromRq(small *out,const Fq *r)
+{
+ int i;
+ for (i = 0;i < p;++i) out[i] = F3_freeze(r[i]);
+}
+
+/* h = f*g in the ring R3 */
+static void R3_mult(small *h,const small *f,const small *g)
+{
+ small fg[p+p-1];
+ small result;
+ int i,j;
+
+ for (i = 0;i < p;++i) {
+ result = 0;
+ for (j = 0;j <= i;++j) result = F3_freeze(result+f[j]*g[i-j]);
+ fg[i] = result;
+ }
+ for (i = p;i < p+p-1;++i) {
+ result = 0;
+ for (j = i-p+1;j < p;++j) result = F3_freeze(result+f[j]*g[i-j]);
+ fg[i] = result;
+ }
+
+ for (i = p+p-2;i >= p;--i) {
+ fg[i-p] = F3_freeze(fg[i-p]+fg[i]);
+ fg[i-p+1] = F3_freeze(fg[i-p+1]+fg[i]);
+ }
+
+ for (i = 0;i < p;++i) h[i] = fg[i];
+}
+
+/* returns 0 if recip succeeded; else -1 */
+static int R3_recip(small *out,const small *in)
+{
+ small f[p+1],g[p+1],v[p+1],r[p+1];
+ int i,loop,delta;
+ int sign,swap,t;
+
+ for (i = 0;i < p+1;++i) v[i] = 0;
+ for (i = 0;i < p+1;++i) r[i] = 0;
+ r[0] = 1;
+ for (i = 0;i < p;++i) f[i] = 0;
+ f[0] = 1; f[p-1] = f[p] = -1;
+ for (i = 0;i < p;++i) g[p-1-i] = in[i];
+ g[p] = 0;
+
+ delta = 1;
+
+ for (loop = 0;loop < 2*p-1;++loop) {
+ for (i = p;i > 0;--i) v[i] = v[i-1];
+ v[0] = 0;
+
+ sign = -g[0]*f[0];
+ swap = int16_negative_mask(-delta) & int16_nonzero_mask(g[0]);
+ delta ^= swap&(delta^-delta);
+ delta += 1;
+
+ for (i = 0;i < p+1;++i) {
+ t = swap&(f[i]^g[i]); f[i] ^= t; g[i] ^= t;
+ t = swap&(v[i]^r[i]); v[i] ^= t; r[i] ^= t;
+ }
+
+ for (i = 0;i < p+1;++i) g[i] = F3_freeze(g[i]+sign*f[i]);
+ for (i = 0;i < p+1;++i) r[i] = F3_freeze(r[i]+sign*v[i]);
+
+ for (i = 0;i < p;++i) g[i] = g[i+1];
+ g[p] = 0;
+ }
+
+ sign = f[0];
+ for (i = 0;i < p;++i) out[i] = sign*v[p-1-i];
+
+ return int16_nonzero_mask(delta);
+}
+
+#endif
+
+/* ----- polynomials mod q */
+
+/* h = f*g in the ring Rq */
+static void Rq_mult_small(Fq *h,const Fq *f,const small *g)
+{
+ Fq fg[p+p-1];
+ Fq result;
+ int i,j;
+
+ for (i = 0;i < p;++i) {
+ result = 0;
+ for (j = 0;j <= i;++j) result = Fq_freeze(result+f[j]*(int32)g[i-j]);
+ fg[i] = result;
+ }
+ for (i = p;i < p+p-1;++i) {
+ result = 0;
+ for (j = i-p+1;j < p;++j) result = Fq_freeze(result+f[j]*(int32)g[i-j]);
+ fg[i] = result;
+ }
+
+ for (i = p+p-2;i >= p;--i) {
+ fg[i-p] = Fq_freeze(fg[i-p]+fg[i]);
+ fg[i-p+1] = Fq_freeze(fg[i-p+1]+fg[i]);
+ }
+
+ for (i = 0;i < p;++i) h[i] = fg[i];
+}
+
+#ifndef LPR
+
+/* h = 3f in Rq */
+static void Rq_mult3(Fq *h,const Fq *f)
+{
+ int i;
+
+ for (i = 0;i < p;++i) h[i] = Fq_freeze(3*f[i]);
+}
+
+/* out = 1/(3*in) in Rq */
+/* returns 0 if recip succeeded; else -1 */
+static int Rq_recip3(Fq *out,const small *in)
+{
+ Fq f[p+1],g[p+1],v[p+1],r[p+1];
+ int i,loop,delta;
+ int swap,t;
+ int32 f0,g0;
+ Fq scale;
+
+ for (i = 0;i < p+1;++i) v[i] = 0;
+ for (i = 0;i < p+1;++i) r[i] = 0;
+ r[0] = Fq_recip(3);
+ for (i = 0;i < p;++i) f[i] = 0;
+ f[0] = 1; f[p-1] = f[p] = -1;
+ for (i = 0;i < p;++i) g[p-1-i] = in[i];
+ g[p] = 0;
+
+ delta = 1;
+
+ for (loop = 0;loop < 2*p-1;++loop) {
+ for (i = p;i > 0;--i) v[i] = v[i-1];
+ v[0] = 0;
+
+ swap = int16_negative_mask(-delta) & int16_nonzero_mask(g[0]);
+ delta ^= swap&(delta^-delta);
+ delta += 1;
+
+ for (i = 0;i < p+1;++i) {
+ t = swap&(f[i]^g[i]); f[i] ^= t; g[i] ^= t;
+ t = swap&(v[i]^r[i]); v[i] ^= t; r[i] ^= t;
+ }
+
+ f0 = f[0];
+ g0 = g[0];
+ for (i = 0;i < p+1;++i) g[i] = Fq_freeze(f0*g[i]-g0*f[i]);
+ for (i = 0;i < p+1;++i) r[i] = Fq_freeze(f0*r[i]-g0*v[i]);
+
+ for (i = 0;i < p;++i) g[i] = g[i+1];
+ g[p] = 0;
+ }
+
+ scale = Fq_recip(f[0]);
+ for (i = 0;i < p;++i) out[i] = Fq_freeze(scale*(int32)v[p-1-i]);
+
+ return int16_nonzero_mask(delta);
+}
+
+#endif
+
+/* ----- rounded polynomials mod q */
+
+static void Round(Fq *out,const Fq *a)
+{
+ int i;
+ for (i = 0;i < p;++i) out[i] = a[i]-F3_freeze(a[i]);
+}
+
+/* ----- sorting to generate short polynomial */
+
+static void Short_fromlist(small *out,const uint32 *in)
+{
+ uint32 L[p];
+ int i;
+
+ for (i = 0;i < w;++i) L[i] = in[i]&(uint32)-2;
+ for (i = w;i < p;++i) L[i] = (in[i]&(uint32)-3)|1;
+ crypto_sort_uint32(L,p);
+ for (i = 0;i < p;++i) out[i] = (L[i]&3)-1;
+}
+
+/* ----- underlying hash function */
+
+#define Hash_bytes 32
+
+/* e.g., b = 0 means out = Hash0(in) */
+static void Hash_prefix(unsigned char *out,int b,const unsigned char *in,int inlen)
+{
+ unsigned char x[inlen+1];
+ unsigned char h[64];
+ int i;
+
+ x[0] = b;
+ for (i = 0;i < inlen;++i) x[i+1] = in[i];
+ crypto_hash_sha512(h,x,inlen+1);
+ for (i = 0;i < 32;++i) out[i] = h[i];
+}
+
+/* ----- higher-level randomness */
+
+static uint32 urandom32(void)
+{
+ unsigned char c[4];
+ uint32 out[4];
+
+ randombytes(c,4);
+ out[0] = (uint32)c[0];
+ out[1] = ((uint32)c[1])<<8;
+ out[2] = ((uint32)c[2])<<16;
+ out[3] = ((uint32)c[3])<<24;
+ return out[0]+out[1]+out[2]+out[3];
+}
+
+static void Short_random(small *out)
+{
+ uint32 L[p];
+ int i;
+
+ for (i = 0;i < p;++i) L[i] = urandom32();
+ Short_fromlist(out,L);
+}
+
+#ifndef LPR
+
+static void Small_random(small *out)
+{
+ int i;
+
+ for (i = 0;i < p;++i) out[i] = (((urandom32()&0x3fffffff)*3)>>30)-1;
+}
+
+#endif
+
+/* ----- Streamlined NTRU Prime Core */
+
+#ifndef LPR
+
+/* h,(f,ginv) = KeyGen() */
+static void KeyGen(Fq *h,small *f,small *ginv)
+{
+ small g[p];
+ Fq finv[p];
+
+ for (;;) {
+ Small_random(g);
+ if (R3_recip(ginv,g) == 0) break;
+ }
+ Short_random(f);
+ Rq_recip3(finv,f); /* always works */
+ Rq_mult_small(h,finv,g);
+}
+
+/* c = Encrypt(r,h) */
+static void Encrypt(Fq *c,const small *r,const Fq *h)
+{
+ Fq hr[p];
+
+ Rq_mult_small(hr,h,r);
+ Round(c,hr);
+}
+
+/* r = Decrypt(c,(f,ginv)) */
+static void Decrypt(small *r,const Fq *c,const small *f,const small *ginv)
+{
+ Fq cf[p];
+ Fq cf3[p];
+ small e[p];
+ small ev[p];
+ int mask;
+ int i;
+
+ Rq_mult_small(cf,c,f);
+ Rq_mult3(cf3,cf);
+ R3_fromRq(e,cf3);
+ R3_mult(ev,e,ginv);
+
+ mask = Weightw_mask(ev); /* 0 if weight w, else -1 */
+ for (i = 0;i < w;++i) r[i] = ((ev[i]^1)&~mask)^1;
+ for (i = w;i < p;++i) r[i] = ev[i]&~mask;
+}
+
+#endif
+
+/* ----- NTRU LPRime Core */
+
+#ifdef LPR
+
+/* (G,A),a = KeyGen(G); leaves G unchanged */
+static void KeyGen(Fq *A,small *a,const Fq *G)
+{
+ Fq aG[p];
+
+ Short_random(a);
+ Rq_mult_small(aG,G,a);
+ Round(A,aG);
+}
+
+/* B,T = Encrypt(r,(G,A),b) */
+static void Encrypt(Fq *B,int8 *T,const int8 *r,const Fq *G,const Fq *A,const small *b)
+{
+ Fq bG[p];
+ Fq bA[p];
+ int i;
+
+ Rq_mult_small(bG,G,b);
+ Round(B,bG);
+ Rq_mult_small(bA,A,b);
+ for (i = 0;i < I;++i) T[i] = Top(Fq_freeze(bA[i]+r[i]*q12));
+}
+
+/* r = Decrypt((B,T),a) */
+static void Decrypt(int8 *r,const Fq *B,const int8 *T,const small *a)
+{
+ Fq aB[p];
+ int i;
+
+ Rq_mult_small(aB,B,a);
+ for (i = 0;i < I;++i)
+ r[i] = -int16_negative_mask(Fq_freeze(Right(T[i])-aB[i]+4*w+1));
+}
+
+#endif
+
+/* ----- encoding I-bit inputs */
+
+#ifdef LPR
+
+#define Inputs_bytes (I/8)
+typedef int8 Inputs[I]; /* passed by reference */
+
+static void Inputs_encode(unsigned char *s,const Inputs r)
+{
+ int i;
+ for (i = 0;i < Inputs_bytes;++i) s[i] = 0;
+ for (i = 0;i < I;++i) s[i>>3] |= r[i]<<(i&7);
+}
+
+#endif
+
+/* ----- Expand */
+
+#ifdef LPR
+
+static const unsigned char aes_nonce[16] = {0};
+
+static void Expand(uint32 *L,const unsigned char *k)
+{
+ int i;
+ crypto_stream_aes256ctr((unsigned char *) L,4*p,aes_nonce,k);
+ for (i = 0;i < p;++i) {
+ uint32 L0 = ((unsigned char *) L)[4*i];
+ uint32 L1 = ((unsigned char *) L)[4*i+1];
+ uint32 L2 = ((unsigned char *) L)[4*i+2];
+ uint32 L3 = ((unsigned char *) L)[4*i+3];
+ L[i] = L0+(L1<<8)+(L2<<16)+(L3<<24);
+ }
+}
+
+#endif
+
+/* ----- Seeds */
+
+#ifdef LPR
+
+#define Seeds_bytes 32
+
+static void Seeds_random(unsigned char *s)
+{
+ randombytes(s,Seeds_bytes);
+}
+
+#endif
+
+/* ----- Generator, HashShort */
+
+#ifdef LPR
+
+/* G = Generator(k) */
+static void Generator(Fq *G,const unsigned char *k)
+{
+ uint32 L[p];
+ int i;
+
+ Expand(L,k);
+ for (i = 0;i < p;++i) G[i] = uint32_mod_uint14(L[i],q)-q12;
+}
+
+/* out = HashShort(r) */
+static void HashShort(small *out,const Inputs r)
+{
+ unsigned char s[Inputs_bytes];
+ unsigned char h[Hash_bytes];
+ uint32 L[p];
+
+ Inputs_encode(s,r);
+ Hash_prefix(h,5,s,sizeof s);
+ Expand(L,h);
+ Short_fromlist(out,L);
+}
+
+#endif
+
+/* ----- NTRU LPRime Expand */
+
+#ifdef LPR
+
+/* (S,A),a = XKeyGen() */
+static void XKeyGen(unsigned char *S,Fq *A,small *a)
+{
+ Fq G[p];
+
+ Seeds_random(S);
+ Generator(G,S);
+ KeyGen(A,a,G);
+}
+
+/* B,T = XEncrypt(r,(S,A)) */
+static void XEncrypt(Fq *B,int8 *T,const int8 *r,const unsigned char *S,const Fq *A)
+{
+ Fq G[p];
+ small b[p];
+
+ Generator(G,S);
+ HashShort(b,r);
+ Encrypt(B,T,r,G,A,b);
+}
+
+#define XDecrypt Decrypt
+
+#endif
+
+/* ----- encoding small polynomials (including short polynomials) */
+
+#define Small_bytes ((p+3)/4)
+
+/* these are the only functions that rely on p mod 4 = 1 */
+
+static void Small_encode(unsigned char *s,const small *f)
+{
+ small x;
+ int i;
+
+ for (i = 0;i < p/4;++i) {
+ x = *f++ + 1;
+ x += (*f++ + 1)<<2;
+ x += (*f++ + 1)<<4;
+ x += (*f++ + 1)<<6;
+ *s++ = x;
+ }
+ x = *f++ + 1;
+ *s++ = x;
+}
+
+static void Small_decode(small *f,const unsigned char *s)
+{
+ unsigned char x;
+ int i;
+
+ for (i = 0;i < p/4;++i) {
+ x = *s++;
+ *f++ = ((small)(x&3))-1; x >>= 2;
+ *f++ = ((small)(x&3))-1; x >>= 2;
+ *f++ = ((small)(x&3))-1; x >>= 2;
+ *f++ = ((small)(x&3))-1;
+ }
+ x = *s++;
+ *f++ = ((small)(x&3))-1;
+}
+
+/* ----- encoding general polynomials */
+
+#ifndef LPR
+
+static void Rq_encode(unsigned char *s,const Fq *r)
+{
+ uint16 R[p],M[p];
+ int i;
+
+ for (i = 0;i < p;++i) R[i] = r[i]+q12;
+ for (i = 0;i < p;++i) M[i] = q;
+ Encode(s,R,M,p);
+}
+
+static void Rq_decode(Fq *r,const unsigned char *s)
+{
+ uint16 R[p],M[p];
+ int i;
+
+ for (i = 0;i < p;++i) M[i] = q;
+ Decode(R,s,M,p);
+ for (i = 0;i < p;++i) r[i] = ((Fq)R[i])-q12;
+}
+
+#endif
+
+/* ----- encoding rounded polynomials */
+
+static void Rounded_encode(unsigned char *s,const Fq *r)
+{
+ uint16 R[p],M[p];
+ int i;
+
+ for (i = 0;i < p;++i) R[i] = ((r[i]+q12)*10923)>>15;
+ for (i = 0;i < p;++i) M[i] = (q+2)/3;
+ Encode(s,R,M,p);
+}
+
+static void Rounded_decode(Fq *r,const unsigned char *s)
+{
+ uint16 R[p],M[p];
+ int i;
+
+ for (i = 0;i < p;++i) M[i] = (q+2)/3;
+ Decode(R,s,M,p);
+ for (i = 0;i < p;++i) r[i] = R[i]*3-q12;
+}
+
+/* ----- encoding top polynomials */
+
+#ifdef LPR
+
+#define Top_bytes (I/2)
+
+static void Top_encode(unsigned char *s,const int8 *T)
+{
+ int i;
+ for (i = 0;i < Top_bytes;++i)
+ s[i] = T[2*i]+(T[2*i+1]<<4);
+}
+
+static void Top_decode(int8 *T,const unsigned char *s)
+{
+ int i;
+ for (i = 0;i < Top_bytes;++i) {
+ T[2*i] = s[i]&15;
+ T[2*i+1] = s[i]>>4;
+ }
+}
+
+#endif
+
+/* ----- Streamlined NTRU Prime Core plus encoding */
+
+#ifndef LPR
+
+typedef small Inputs[p]; /* passed by reference */
+#define Inputs_random Short_random
+#define Inputs_encode Small_encode
+#define Inputs_bytes Small_bytes
+
+#define Ciphertexts_bytes Rounded_bytes
+#define SecretKeys_bytes (2*Small_bytes)
+#define PublicKeys_bytes Rq_bytes
+
+/* pk,sk = ZKeyGen() */
+static void ZKeyGen(unsigned char *pk,unsigned char *sk)
+{
+ Fq h[p];
+ small f[p],v[p];
+
+ KeyGen(h,f,v);
+ Rq_encode(pk,h);
+ Small_encode(sk,f); sk += Small_bytes;
+ Small_encode(sk,v);
+}
+
+/* C = ZEncrypt(r,pk) */
+static void ZEncrypt(unsigned char *C,const Inputs r,const unsigned char *pk)
+{
+ Fq h[p];
+ Fq c[p];
+ Rq_decode(h,pk);
+ Encrypt(c,r,h);
+ Rounded_encode(C,c);
+}
+
+/* r = ZDecrypt(C,sk) */
+static void ZDecrypt(Inputs r,const unsigned char *C,const unsigned char *sk)
+{
+ small f[p],v[p];
+ Fq c[p];
+
+ Small_decode(f,sk); sk += Small_bytes;
+ Small_decode(v,sk);
+ Rounded_decode(c,C);
+ Decrypt(r,c,f,v);
+}
+
+#endif
+
+/* ----- NTRU LPRime Expand plus encoding */
+
+#ifdef LPR
+
+#define Ciphertexts_bytes (Rounded_bytes+Top_bytes)
+#define SecretKeys_bytes Small_bytes
+#define PublicKeys_bytes (Seeds_bytes+Rounded_bytes)
+
+static void Inputs_random(Inputs r)
+{
+ unsigned char s[Inputs_bytes];
+ int i;
+
+ randombytes(s,sizeof s);
+ for (i = 0;i < I;++i) r[i] = 1&(s[i>>3]>>(i&7));
+}
+
+/* pk,sk = ZKeyGen() */
+static void ZKeyGen(unsigned char *pk,unsigned char *sk)
+{
+ Fq A[p];
+ small a[p];
+
+ XKeyGen(pk,A,a); pk += Seeds_bytes;
+ Rounded_encode(pk,A);
+ Small_encode(sk,a);
+}
+
+/* c = ZEncrypt(r,pk) */
+static void ZEncrypt(unsigned char *c,const Inputs r,const unsigned char *pk)
+{
+ Fq A[p];
+ Fq B[p];
+ int8 T[I];
+
+ Rounded_decode(A,pk+Seeds_bytes);
+ XEncrypt(B,T,r,pk,A);
+ Rounded_encode(c,B); c += Rounded_bytes;
+ Top_encode(c,T);
+}
+
+/* r = ZDecrypt(C,sk) */
+static void ZDecrypt(Inputs r,const unsigned char *c,const unsigned char *sk)
+{
+ small a[p];
+ Fq B[p];
+ int8 T[I];
+
+ Small_decode(a,sk);
+ Rounded_decode(B,c);
+ Top_decode(T,c+Rounded_bytes);
+ XDecrypt(r,B,T,a);
+}
+
+#endif
+
+/* ----- confirmation hash */
+
+#define Confirm_bytes 32
+
+/* h = HashConfirm(r,pk,cache); cache is Hash4(pk) */
+static void HashConfirm(unsigned char *h,const unsigned char *r,const unsigned char *pk,const unsigned char *cache)
+{
+#ifndef LPR
+ unsigned char x[Hash_bytes*2];
+ int i;
+
+ Hash_prefix(x,3,r,Inputs_bytes);
+ for (i = 0;i < Hash_bytes;++i) x[Hash_bytes+i] = cache[i];
+#else
+ unsigned char x[Inputs_bytes+Hash_bytes];
+ int i;
+
+ for (i = 0;i < Inputs_bytes;++i) x[i] = r[i];
+ for (i = 0;i < Hash_bytes;++i) x[Inputs_bytes+i] = cache[i];
+#endif
+ Hash_prefix(h,2,x,sizeof x);
+}
+
+/* ----- session-key hash */
+
+/* k = HashSession(b,y,z) */
+static void HashSession(unsigned char *k,int b,const unsigned char *y,const unsigned char *z)
+{
+#ifndef LPR
+ unsigned char x[Hash_bytes+Ciphertexts_bytes+Confirm_bytes];
+ int i;
+
+ Hash_prefix(x,3,y,Inputs_bytes);
+ for (i = 0;i < Ciphertexts_bytes+Confirm_bytes;++i) x[Hash_bytes+i] = z[i];
+#else
+ unsigned char x[Inputs_bytes+Ciphertexts_bytes+Confirm_bytes];
+ int i;
+
+ for (i = 0;i < Inputs_bytes;++i) x[i] = y[i];
+ for (i = 0;i < Ciphertexts_bytes+Confirm_bytes;++i) x[Inputs_bytes+i] = z[i];
+#endif
+ Hash_prefix(k,b,x,sizeof x);
+}
+
+/* ----- Streamlined NTRU Prime and NTRU LPRime */
+
+/* pk,sk = KEM_KeyGen() */
+static void KEM_KeyGen(unsigned char *pk,unsigned char *sk)
+{
+ int i;
+
+ ZKeyGen(pk,sk); sk += SecretKeys_bytes;
+ for (i = 0;i < PublicKeys_bytes;++i) *sk++ = pk[i];
+ randombytes(sk,Inputs_bytes); sk += Inputs_bytes;
+ Hash_prefix(sk,4,pk,PublicKeys_bytes);
+}
+
+/* c,r_enc = Hide(r,pk,cache); cache is Hash4(pk) */
+static void Hide(unsigned char *c,unsigned char *r_enc,const Inputs r,const unsigned char *pk,const unsigned char *cache)
+{
+ Inputs_encode(r_enc,r);
+ ZEncrypt(c,r,pk); c += Ciphertexts_bytes;
+ HashConfirm(c,r_enc,pk,cache);
+}
+
+/* c,k = Encap(pk) */
+static void Encap(unsigned char *c,unsigned char *k,const unsigned char *pk)
+{
+ Inputs r;
+ unsigned char r_enc[Inputs_bytes];
+ unsigned char cache[Hash_bytes];
+
+ Hash_prefix(cache,4,pk,PublicKeys_bytes);
+ Inputs_random(r);
+ Hide(c,r_enc,r,pk,cache);
+ HashSession(k,1,r_enc,c);
+}
+
+/* 0 if matching ciphertext+confirm, else -1 */
+static int Ciphertexts_diff_mask(const unsigned char *c,const unsigned char *c2)
+{
+ uint16 differentbits = 0;
+ int len = Ciphertexts_bytes+Confirm_bytes;
+
+ while (len-- > 0) differentbits |= (*c++)^(*c2++);
+ return (1&((differentbits-1)>>8))-1;
+}
+
+/* k = Decap(c,sk) */
+static void Decap(unsigned char *k,const unsigned char *c,const unsigned char *sk)
+{
+ const unsigned char *pk = sk + SecretKeys_bytes;
+ const unsigned char *rho = pk + PublicKeys_bytes;
+ const unsigned char *cache = rho + Inputs_bytes;
+ Inputs r;
+ unsigned char r_enc[Inputs_bytes];
+ unsigned char cnew[Ciphertexts_bytes+Confirm_bytes];
+ int mask;
+ int i;
+
+ ZDecrypt(r,c,sk);
+ Hide(cnew,r_enc,r,pk,cache);
+ mask = Ciphertexts_diff_mask(c,cnew);
+ for (i = 0;i < Inputs_bytes;++i) r_enc[i] ^= mask&(r_enc[i]^rho[i]);
+ HashSession(k,1+mask,r_enc,c);
+}
+
+/* ----- crypto_kem API */
+
+
+int crypto_kem_sntrup761_keypair(unsigned char *pk,unsigned char *sk)
+{
+ KEM_KeyGen(pk,sk);
+ return 0;
+}
+
+int crypto_kem_sntrup761_enc(unsigned char *c,unsigned char *k,const unsigned char *pk)
+{
+ Encap(c,k,pk);
+ return 0;
+}
+
+int crypto_kem_sntrup761_dec(unsigned char *k,const unsigned char *c,const unsigned char *sk)
+{
+ Decap(k,c,sk);
+ return 0;
+}
+#endif /* USE_SNTRUP761X25519 */
diff --git a/sntrup761.sh b/sntrup761.sh
new file mode 100644
index 000000000..5cd5f92c3
--- /dev/null
+++ b/sntrup761.sh
@@ -0,0 +1,85 @@
+#!/bin/sh
+# $OpenBSD: sntrup761.sh,v 1.5 2021/01/08 02:33:13 dtucker Exp $
+# Placed in the Public Domain.
+#
+AUTHOR="supercop-20201130/crypto_kem/sntrup761/ref/implementors"
+FILES="
+ supercop-20201130/crypto_sort/int32/portable4/int32_minmax.inc
+ supercop-20201130/crypto_sort/int32/portable4/sort.c
+ supercop-20201130/crypto_sort/uint32/useint32/sort.c
+ supercop-20201130/crypto_kem/sntrup761/ref/uint32.c
+ supercop-20201130/crypto_kem/sntrup761/ref/int32.c
+ supercop-20201130/crypto_kem/sntrup761/ref/paramsmenu.h
+ supercop-20201130/crypto_kem/sntrup761/ref/params.h
+ supercop-20201130/crypto_kem/sntrup761/ref/Decode.h
+ supercop-20201130/crypto_kem/sntrup761/ref/Decode.c
+ supercop-20201130/crypto_kem/sntrup761/ref/Encode.h
+ supercop-20201130/crypto_kem/sntrup761/ref/Encode.c
+ supercop-20201130/crypto_kem/sntrup761/ref/kem.c
+"
+###
+
+set -e
+cd $1
+echo -n '/* $'
+echo 'OpenBSD: $ */'
+echo
+echo '/*'
+echo ' * Public Domain, Authors:'
+sed -e '/Alphabetical order:/d' -e 's/^/ * - /' < $AUTHOR
+echo ' */'
+echo
+echo '#include <string.h>'
+echo '#include "crypto_api.h"'
+echo
+# Map the types used in this code to the ones in crypto_api.h. We use #define
+# instead of typedef since some systems have existing intXX types and do not
+# permit multiple typedefs even if they do not conflict.
+for t in int8 uint8 int16 uint16 int32 uint32 int64 uint64; do
+ echo "#define $t crypto_${t}"
+done
+echo
+for i in $FILES; do
+ echo "/* from $i */"
+ # Changes to all files:
+ # - remove all includes, we inline everything required.
+ # - make functions not required elsewhere static.
+ # - rename the functions we do use.
+ # - remove unneccesary defines and externs.
+ sed -e "/#include/d" \
+ -e "s/crypto_kem_/crypto_kem_sntrup761_/g" \
+ -e "s/^void /static void /g" \
+ -e "s/^int16 /static int16 /g" \
+ -e "s/^uint16 /static uint16 /g" \
+ -e "/^extern /d" \
+ -e '/CRYPTO_NAMESPACE/d' \
+ -e "/^#define int32 crypto_int32/d" \
+ $i | \
+ case "$i" in
+ # Use int64_t for intermediate values in int32_MINMAX to prevent signed
+ # 32-bit integer overflow when called by crypto_sort_uint32.
+ */int32_minmax.inc)
+ sed -e "s/int32 ab = b ^ a/int64_t ab = (int64_t)b ^ (int64_t)a/" \
+ -e "s/int32 c = b - a/int64_t c = (int64_t)b - (int64_t)a/"
+ ;;
+ */int32/portable4/sort.c)
+ sed -e "s/void crypto_sort/void crypto_sort_int32/g"
+ ;;
+ */uint32/useint32/sort.c)
+ sed -e "s/void crypto_sort/void crypto_sort_uint32/g"
+ ;;
+ # Remove unused function to prevent warning.
+ */crypto_kem/sntrup761/ref/int32.c)
+ sed -e '/ int32_div_uint14/,/^}$/d'
+ ;;
+ # Remove unused function to prevent warning.
+ */crypto_kem/sntrup761/ref/uint32.c)
+ sed -e '/ uint32_div_uint14/,/^}$/d'
+ ;;
+ # Default: pass through.
+ *)
+ cat
+ ;;
+ esac
+ echo
+done
diff --git a/srclimit.c b/srclimit.c
new file mode 100644
index 000000000..5014ed79f
--- /dev/null
+++ b/srclimit.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2020 Darren Tucker <dtucker@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#include <limits.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "addr.h"
+#include "canohost.h"
+#include "log.h"
+#include "misc.h"
+#include "srclimit.h"
+#include "xmalloc.h"
+
+static int max_children, max_persource, ipv4_masklen, ipv6_masklen;
+
+/* Per connection state, used to enforce unauthenticated connection limit. */
+static struct child_info {
+ int id;
+ struct xaddr addr;
+} *child;
+
+void
+srclimit_init(int max, int persource, int ipv4len, int ipv6len)
+{
+ int i;
+
+ max_children = max;
+ ipv4_masklen = ipv4len;
+ ipv6_masklen = ipv6len;
+ max_persource = persource;
+ if (max_persource == INT_MAX) /* no limit */
+ return;
+ debug("%s: max connections %d, per source %d, masks %d,%d", __func__,
+ max, persource, ipv4len, ipv6len);
+ if (max <= 0)
+ fatal("%s: invalid number of sockets: %d", __func__, max);
+ child = xcalloc(max_children, sizeof(*child));
+ for (i = 0; i < max_children; i++)
+ child[i].id = -1;
+}
+
+/* returns 1 if connection allowed, 0 if not allowed. */
+int
+srclimit_check_allow(int sock, int id)
+{
+ struct xaddr xa, xb, xmask;
+ struct sockaddr_storage addr;
+ socklen_t addrlen = sizeof(addr);
+ struct sockaddr *sa = (struct sockaddr *)&addr;
+ int i, bits, first_unused, count = 0;
+ char xas[NI_MAXHOST];
+
+ if (max_persource == INT_MAX) /* no limit */
+ return 1;
+
+ debug("%s: sock %d id %d limit %d", __func__, sock, id, max_persource);
+ if (getpeername(sock, sa, &addrlen) != 0)
+ return 1; /* not remote socket? */
+ if (addr_sa_to_xaddr(sa, addrlen, &xa) != 0)
+ return 1; /* unknown address family? */
+
+ /* Mask address off address to desired size. */
+ bits = xa.af == AF_INET ? ipv4_masklen : ipv6_masklen;
+ if (addr_netmask(xa.af, bits, &xmask) != 0 ||
+ addr_and(&xb, &xa, &xmask) != 0) {
+ debug3("%s: invalid mask %d bits", __func__, bits);
+ return 1;
+ }
+
+ first_unused = max_children;
+ /* Count matching entries and find first unused one. */
+ for (i = 0; i < max_children; i++) {
+ if (child[i].id == -1) {
+ if (i < first_unused)
+ first_unused = i;
+ } else if (addr_cmp(&child[i].addr, &xb) == 0) {
+ count++;
+ }
+ }
+ if (addr_ntop(&xa, xas, sizeof(xas)) != 0) {
+ debug3("%s: addr ntop failed", __func__);
+ return 1;
+ }
+ debug3("%s: new unauthenticated connection from %s/%d, at %d of %d",
+ __func__, xas, bits, count, max_persource);
+
+ if (first_unused == max_children) { /* no free slot found */
+ debug3("%s: no free slot", __func__);
+ return 0;
+ }
+ if (first_unused < 0 || first_unused >= max_children)
+ fatal("%s: internal error: first_unused out of range",
+ __func__);
+
+ if (count >= max_persource)
+ return 0;
+
+ /* Connection allowed, store masked address. */
+ child[first_unused].id = id;
+ memcpy(&child[first_unused].addr, &xb, sizeof(xb));
+ return 1;
+}
+
+void
+srclimit_done(int id)
+{
+ int i;
+
+ if (max_persource == INT_MAX) /* no limit */
+ return;
+
+ debug("%s: id %d", __func__, id);
+ /* Clear corresponding state entry. */
+ for (i = 0; i < max_children; i++) {
+ if (child[i].id == id) {
+ child[i].id = -1;
+ return;
+ }
+ }
+}
diff --git a/srclimit.h b/srclimit.h
new file mode 100644
index 000000000..6e04f32b3
--- /dev/null
+++ b/srclimit.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020 Darren Tucker <dtucker@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+void srclimit_init(int, int, int, int);
+int srclimit_check_allow(int, int);
+void srclimit_done(int);
diff --git a/ssh-add.1 b/ssh-add.1
index 58d42138e..2786df514 100644
--- a/ssh-add.1
+++ b/ssh-add.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ssh-add.1,v 1.79 2020/02/07 03:57:31 djm Exp $
+.\" $OpenBSD: ssh-add.1,v 1.81 2020/07/14 23:57:01 djm Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, 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: February 7 2020 $
+.Dd $Mdocdate: July 14 2020 $
.Dt SSH-ADD 1
.Os
.Sh NAME
@@ -113,6 +113,11 @@ If no public key is found at a given path,
will append
.Pa .pub
and retry.
+If the argument list consists of
+.Dq -
+then
+.Nm
+will read public keys to be removed from standard input.
.It Fl E Ar fingerprint_hash
Specifies the hash algorithm used when displaying key fingerprints.
Valid options are:
@@ -169,7 +174,7 @@ Lock the agent with a password.
.El
.Sh ENVIRONMENT
.Bl -tag -width Ds
-.It Ev "DISPLAY" and "SSH_ASKPASS"
+.It Ev "DISPLAY", "SSH_ASKPASS" and "SSH_ASKPASS_REQUIRE"
If
.Nm
needs a passphrase, it will read the passphrase from the current
@@ -190,10 +195,26 @@ This is particularly useful when calling
from a
.Pa .xsession
or related script.
-(Note that on some machines it
-may be necessary to redirect the input from
-.Pa /dev/null
-to make this work.)
+.Pp
+.Ev SSH_ASKPASS_REQUIRE
+allows further control over the use of an askpass program.
+If this variable is set to
+.Dq never
+then
+.Nm
+will never attempt to use one.
+If it is set to
+.Dq prefer ,
+then
+.Nm
+will prefer to use the askpass program instead of the TTY when requesting
+passwords.
+Finally, if the variable is set to
+.Dq force ,
+then the askpass program will be used for all passphrase input regardless
+of whether
+.Ev DISPLAY
+is set.
.It Ev SSH_AUTH_SOCK
Identifies the path of a
.Ux Ns -domain
diff --git a/ssh-add.c b/ssh-add.c
index a40198ab5..92192fcfa 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-add.c,v 1.155 2020/03/16 02:17:02 dtucker Exp $ */
+/* $OpenBSD: ssh-add.c,v 1.160 2021/04/03 06:18:41 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -67,6 +67,7 @@
#include "ssherr.h"
#include "digest.h"
#include "ssh-sk.h"
+#include "sk-api.h"
/* argv0 */
extern char *__progname;
@@ -90,7 +91,7 @@ static char *default_files[] = {
static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
/* Default lifetime (0 == forever) */
-static long lifetime = 0;
+static int lifetime = 0;
/* User has to confirm key use */
static int confirm = 0;
@@ -111,25 +112,69 @@ clear_pass(void)
}
static int
+delete_one(int agent_fd, const struct sshkey *key, const char *comment,
+ const char *path, int qflag)
+{
+ int r;
+
+ if ((r = ssh_remove_identity(agent_fd, key)) != 0) {
+ fprintf(stderr, "Could not remove identity \"%s\": %s\n",
+ path, ssh_err(r));
+ return r;
+ }
+ if (!qflag) {
+ fprintf(stderr, "Identity removed: %s %s (%s)\n", path,
+ sshkey_type(key), comment);
+ }
+ return 0;
+}
+
+static int
+delete_stdin(int agent_fd, int qflag)
+{
+ char *line = NULL, *cp;
+ size_t linesize = 0;
+ struct sshkey *key = NULL;
+ int lnum = 0, r, ret = -1;
+
+ while (getline(&line, &linesize, stdin) != -1) {
+ lnum++;
+ sshkey_free(key);
+ key = NULL;
+ line[strcspn(line, "\n")] = '\0';
+ cp = line + strspn(line, " \t");
+ if (*cp == '#' || *cp == '\0')
+ continue;
+ if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
+ fatal_f("sshkey_new");
+ if ((r = sshkey_read(key, &cp)) != 0) {
+ error_r(r, "(stdin):%d: invalid key", lnum);
+ continue;
+ }
+ if (delete_one(agent_fd, key, cp, "(stdin)", qflag) == 0)
+ ret = 0;
+ }
+ sshkey_free(key);
+ free(line);
+ return ret;
+}
+
+static int
delete_file(int agent_fd, const char *filename, int key_only, int qflag)
{
struct sshkey *public, *cert = NULL;
char *certpath = NULL, *comment = NULL;
int r, ret = -1;
+ if (strcmp(filename, "-") == 0)
+ return delete_stdin(agent_fd, qflag);
+
if ((r = sshkey_load_public(filename, &public, &comment)) != 0) {
printf("Bad key file %s: %s\n", filename, ssh_err(r));
return -1;
}
- if ((r = ssh_remove_identity(agent_fd, public)) == 0) {
- if (!qflag) {
- fprintf(stderr, "Identity removed: %s (%s)\n",
- filename, comment);
- }
+ if (delete_one(agent_fd, public, comment, filename, qflag) == 0)
ret = 0;
- } else
- fprintf(stderr, "Could not remove identity \"%s\": %s\n",
- filename, ssh_err(r));
if (key_only)
goto out;
@@ -140,8 +185,7 @@ delete_file(int agent_fd, const char *filename, int key_only, int qflag)
xasprintf(&certpath, "%s-cert.pub", filename);
if ((r = sshkey_load_public(certpath, &cert, &comment)) != 0) {
if (r != SSH_ERR_SYSTEM_ERROR || errno != ENOENT)
- error("Failed to load certificate \"%s\": %s",
- certpath, ssh_err(r));
+ error_r(r, "Failed to load certificate \"%s\"", certpath);
goto out;
}
@@ -149,15 +193,8 @@ delete_file(int agent_fd, const char *filename, int key_only, int qflag)
fatal("Certificate %s does not match private key %s",
certpath, filename);
- if ((r = ssh_remove_identity(agent_fd, cert)) == 0) {
- if (!qflag) {
- fprintf(stderr, "Identity removed: %s (%s)\n",
- certpath, comment);
- }
+ if (delete_one(agent_fd, cert, comment, certpath, qflag) == 0)
ret = 0;
- } else
- fprintf(stderr, "Could not remove identity \"%s\": %s\n",
- certpath, ssh_err(r));
out:
sshkey_free(cert);
@@ -299,10 +336,10 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag,
fprintf(stderr, "Skipping update: ");
if (left == minleft) {
fprintf(stderr,
- "required signatures left (%d).\n", left);
+ "required signatures left (%d).\n", left);
} else {
fprintf(stderr,
- "more signatures left (%d) than"
+ "more signatures left (%d) than"
" required (%d).\n", left, minleft);
}
ssh_free_identitylist(idlist);
@@ -311,12 +348,20 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag,
ssh_free_identitylist(idlist);
}
- if (!sshkey_is_sk(private))
- skprovider = NULL; /* Don't send constraint for other keys */
- else if (skprovider == NULL) {
- fprintf(stderr, "Cannot load authenticator-hosted key %s "
- "without provider\n", filename);
- goto out;
+ if (sshkey_is_sk(private)) {
+ if (skprovider == NULL) {
+ fprintf(stderr, "Cannot load FIDO key %s "
+ "without provider\n", filename);
+ goto out;
+ }
+ if ((private->sk_flags & SSH_SK_USER_VERIFICATION_REQD) != 0) {
+ fprintf(stderr, "FIDO verify-required key %s is not "
+ "currently supported by ssh-agent\n", filename);
+ goto out;
+ }
+ } else {
+ /* Don't send provider constraint for other keys */
+ skprovider = NULL;
}
if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
@@ -327,7 +372,7 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag,
filename, comment);
if (lifetime != 0) {
fprintf(stderr,
- "Lifetime set to %ld seconds\n", lifetime);
+ "Lifetime set to %d seconds\n", lifetime);
}
if (confirm != 0) {
fprintf(stderr, "The user must confirm "
@@ -347,8 +392,7 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag,
xasprintf(&certpath, "%s-cert.pub", filename);
if ((r = sshkey_load_public(certpath, &cert, NULL)) != 0) {
if (r != SSH_ERR_SYSTEM_ERROR || errno != ENOENT)
- error("Failed to load certificate \"%s\": %s",
- certpath, ssh_err(r));
+ error_r(r, "Failed to load certificate \"%s\"", certpath);
goto out;
}
@@ -361,12 +405,12 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag,
/* Graft with private bits */
if ((r = sshkey_to_certified(private)) != 0) {
- error("%s: sshkey_to_certified: %s", __func__, ssh_err(r));
+ error_fr(r, "sshkey_to_certified");
sshkey_free(cert);
goto out;
}
if ((r = sshkey_cert_copy(cert, private)) != 0) {
- error("%s: sshkey_cert_copy: %s", __func__, ssh_err(r));
+ error_fr(r, "sshkey_cert_copy");
sshkey_free(cert);
goto out;
}
@@ -374,8 +418,8 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag,
if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
lifetime, confirm, maxsign, skprovider)) != 0) {
- error("Certificate %s (%s) add failed: %s", certpath,
- private->cert->key_id, ssh_err(r));
+ error_r(r, "Certificate %s (%s) add failed", certpath,
+ private->cert->key_id);
goto out;
}
/* success */
@@ -383,7 +427,7 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag,
fprintf(stderr, "Certificate added: %s (%s)\n", certpath,
private->cert->key_id);
if (lifetime != 0) {
- fprintf(stderr, "Lifetime set to %ld seconds\n",
+ fprintf(stderr, "Lifetime set to %d seconds\n",
lifetime);
}
if (confirm != 0) {
@@ -438,20 +482,18 @@ test_key(int agent_fd, const char *filename)
char data[1024];
if ((r = sshkey_load_public(filename, &key, NULL)) != 0) {
- error("Couldn't read public key %s: %s", filename, ssh_err(r));
+ error_r(r, "Couldn't read public key %s", filename);
return -1;
}
arc4random_buf(data, sizeof(data));
if ((r = ssh_agent_sign(agent_fd, key, &sig, &slen, data, sizeof(data),
NULL, 0)) != 0) {
- error("Agent signature failed for %s: %s",
- filename, ssh_err(r));
+ error_r(r, "Agent signature failed for %s", filename);
goto done;
}
if ((r = sshkey_verify(key, sig, slen, data, sizeof(data),
NULL, 0, NULL)) != 0) {
- error("Signature verification failed for %s: %s",
- filename, ssh_err(r));
+ error_r(r, "Signature verification failed for %s", filename);
goto done;
}
/* success */
@@ -546,13 +588,13 @@ load_resident_keys(int agent_fd, const char *skprovider, int qflag)
pass = read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN);
if ((r = sshsk_load_resident(skprovider, NULL, pass,
&keys, &nkeys)) != 0) {
- error("Unable to load resident keys: %s", ssh_err(r));
+ error_r(r, "Unable to load resident keys");
return r;
}
for (i = 0; i < nkeys; i++) {
if ((fp = sshkey_fingerprint(keys[i],
fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
- fatal("%s: sshkey_fingerprint failed", __func__);
+ fatal_f("sshkey_fingerprint failed");
if ((r = ssh_add_identity_constrained(agent_fd, keys[i], "",
lifetime, confirm, maxsign, skprovider)) != 0) {
error("Unable to add key %s %s",
@@ -568,7 +610,7 @@ load_resident_keys(int agent_fd, const char *skprovider, int qflag)
sshkey_type(keys[i]), fp);
if (lifetime != 0) {
fprintf(stderr,
- "Lifetime set to %ld seconds\n", lifetime);
+ "Lifetime set to %d seconds\n", lifetime);
}
if (confirm != 0) {
fprintf(stderr, "The user must confirm "
diff --git a/ssh-agent.1 b/ssh-agent.1
index fff0db6bc..ed8c87096 100644
--- a/ssh-agent.1
+++ b/ssh-agent.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ssh-agent.1,v 1.70 2019/12/21 20:22:34 naddy Exp $
+.\" $OpenBSD: ssh-agent.1,v 1.72 2020/06/22 05:52:05 djm Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, 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: December 21 2019 $
+.Dd $Mdocdate: June 22 2020 $
.Dt SSH-AGENT 1
.Os
.Sh NAME
@@ -46,9 +46,14 @@
.Op Fl \&Dd
.Op Fl a Ar bind_address
.Op Fl E Ar fingerprint_hash
-.Op Fl P Ar provider_whitelist
+.Op Fl P Ar allowed_providers
.Op Fl t Ar life
-.Op Ar command Op Ar arg ...
+.Nm ssh-agent
+.Op Fl a Ar bind_address
+.Op Fl E Ar fingerprint_hash
+.Op Fl P Ar allowed_providers
+.Op Fl t Ar life
+.Ar command Op Ar arg ...
.Nm ssh-agent
.Op Fl c | s
.Fl k
@@ -97,19 +102,19 @@ The default is
Kill the current agent (given by the
.Ev SSH_AGENT_PID
environment variable).
-.It Fl P Ar provider_whitelist
-Specify a pattern-list of acceptable paths for PKCS#11 and FIDO authenticator
-shared libraries that may be used with the
+.It Fl P Ar allowed_providers
+Specify a pattern-list of acceptable paths for PKCS#11 provider and FIDO
+authenticator middleware shared libraries that may be used with the
.Fl S
or
.Fl s
options to
.Xr ssh-add 1 .
-Libraries that do not match the whitelist will be refused.
+Libraries that do not match the pattern list will be refused.
See PATTERNS in
.Xr ssh_config 5
for a description of pattern-list syntax.
-The default whitelist is
+The default list is
.Dq /usr/lib/*,/usr/local/lib/* .
.It Fl s
Generate Bourne shell commands on
@@ -152,7 +157,8 @@ which in turn can be evaluated in the calling shell, for example
.Pp
In both cases,
.Xr ssh 1
-looks at these environment variables and uses them to establish a connection to the agent.
+looks at these environment variables
+and uses them to establish a connection to the agent.
.Pp
The agent initially does not have any private keys.
Keys are added using
diff --git a/ssh-agent.c b/ssh-agent.c
index e081413b8..48a47d45a 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-agent.c,v 1.257 2020/03/06 18:28:27 markus Exp $ */
+/* $OpenBSD: ssh-agent.c,v 1.278 2021/04/03 06:18:41 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -77,6 +77,7 @@
#include "xmalloc.h"
#include "ssh.h"
+#include "ssh2.h"
#include "sshbuf.h"
#include "sshkey.h"
#include "authfd.h"
@@ -92,8 +93,8 @@
#include "ssh-pkcs11.h"
#include "sk-api.h"
-#ifndef DEFAULT_PROVIDER_WHITELIST
-# define DEFAULT_PROVIDER_WHITELIST "/usr/lib*/*,/usr/local/lib*/*"
+#ifndef DEFAULT_ALLOWED_PROVIDERS
+# define DEFAULT_ALLOWED_PROVIDERS "/usr/lib*/*,/usr/local/lib*/*"
#endif
/* Maximum accepted message length */
@@ -102,12 +103,12 @@
#define AGENT_RBUF_LEN (4096)
typedef enum {
- AUTH_UNUSED,
- AUTH_SOCKET,
- AUTH_CONNECTION
+ AUTH_UNUSED = 0,
+ AUTH_SOCKET = 1,
+ AUTH_CONNECTION = 2,
} sock_type;
-typedef struct {
+typedef struct socket_entry {
int fd;
sock_type type;
struct sshbuf *input;
@@ -149,8 +150,8 @@ pid_t cleanup_pid = 0;
char socket_name[PATH_MAX];
char socket_dir[PATH_MAX];
-/* PKCS#11/Security key path whitelist */
-static char *provider_whitelist;
+/* Pattern-list of allowed PKCS#11/Security key paths */
+static char *allowed_providers;
/* locking */
#define LOCK_SIZE 32
@@ -163,19 +164,23 @@ u_char lock_salt[LOCK_SALT_SIZE];
extern char *__progname;
/* Default lifetime in seconds (0 == forever) */
-static long lifetime = 0;
+static int lifetime = 0;
static int fingerprint_hash = SSH_FP_HASH_DEFAULT;
+/* Refuse signing of non-SSH messages for web-origin FIDO keys */
+static int restrict_websafe = 1;
+
static void
close_socket(SocketEntry *e)
{
close(e->fd);
- e->fd = -1;
- e->type = AUTH_UNUSED;
sshbuf_free(e->input);
sshbuf_free(e->output);
sshbuf_free(e->request);
+ memset(e, '\0', sizeof(*e));
+ e->fd = -1;
+ e->type = AUTH_UNUSED;
}
static void
@@ -211,15 +216,16 @@ lookup_identity(struct sshkey *key)
/* Check confirmation of keysign request */
static int
-confirm_key(Identity *id)
+confirm_key(Identity *id, const char *extra)
{
char *p;
int ret = -1;
p = sshkey_fingerprint(id->key, fingerprint_hash, SSH_FP_DEFAULT);
if (p != NULL &&
- ask_permission("Allow use of key %s?\nKey fingerprint %s.",
- id->comment, p))
+ ask_permission("Allow use of key %s?\nKey fingerprint %s.%s%s",
+ id->comment, p,
+ extra == NULL ? "" : "\n", extra == NULL ? "" : extra))
ret = 0;
free(p);
@@ -234,7 +240,7 @@ send_status(SocketEntry *e, int success)
if ((r = sshbuf_put_u32(e->output, 1)) != 0 ||
(r = sshbuf_put_u8(e->output, success ?
SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
}
/* send list of supported public keys to 'client' */
@@ -245,22 +251,23 @@ process_request_identities(SocketEntry *e)
struct sshbuf *msg;
int r;
+ debug2_f("entering");
+
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
(r = sshbuf_put_u32(msg, idtab->nentries)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
TAILQ_FOREACH(id, &idtab->idlist, next) {
- if ((r = sshkey_puts_opts(id->key, msg, SSHKEY_SERIALIZE_INFO))
- != 0 ||
+ if ((r = sshkey_puts_opts(id->key, msg,
+ SSHKEY_SERIALIZE_INFO)) != 0 ||
(r = sshbuf_put_cstring(msg, id->comment)) != 0) {
- error("%s: put key/comment: %s", __func__,
- ssh_err(r));
+ error_fr(r, "compose key/comment");
continue;
}
}
if ((r = sshbuf_put_stringb(e->output, msg)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "enqueue");
sshbuf_free(msg);
}
@@ -282,70 +289,213 @@ agent_decode_alg(struct sshkey *key, u_int flags)
return NULL;
}
+/*
+ * Attempt to parse the contents of a buffer as a SSH publickey userauth
+ * request, checking its contents for consistency and matching the embedded
+ * key against the one that is being used for signing.
+ * Note: does not modify msg buffer.
+ * Optionally extract the username and session ID from the request.
+ */
+static int
+parse_userauth_request(struct sshbuf *msg, const struct sshkey *expected_key,
+ char **userp, struct sshbuf **sess_idp)
+{
+ struct sshbuf *b = NULL, *sess_id = NULL;
+ char *user = NULL, *service = NULL, *method = NULL, *pkalg = NULL;
+ int r;
+ u_char t, sig_follows;
+ struct sshkey *mkey = NULL;
+
+ if (userp != NULL)
+ *userp = NULL;
+ if (sess_idp != NULL)
+ *sess_idp = NULL;
+ if ((b = sshbuf_fromb(msg)) == NULL)
+ fatal_f("sshbuf_fromb");
+
+ /* SSH userauth request */
+ if ((r = sshbuf_froms(b, &sess_id)) != 0)
+ goto out;
+ if (sshbuf_len(sess_id) == 0) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if ((r = sshbuf_get_u8(b, &t)) != 0 || /* SSH2_MSG_USERAUTH_REQUEST */
+ (r = sshbuf_get_cstring(b, &user, NULL)) != 0 || /* server user */
+ (r = sshbuf_get_cstring(b, &service, NULL)) != 0 || /* service */
+ (r = sshbuf_get_cstring(b, &method, NULL)) != 0 || /* method */
+ (r = sshbuf_get_u8(b, &sig_follows)) != 0 || /* sig-follows */
+ (r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0 || /* alg */
+ (r = sshkey_froms(b, &mkey)) != 0) /* key */
+ goto out;
+ if (t != SSH2_MSG_USERAUTH_REQUEST ||
+ sig_follows != 1 ||
+ strcmp(service, "ssh-connection") != 0 ||
+ !sshkey_equal(expected_key, mkey) ||
+ sshkey_type_from_name(pkalg) != expected_key->type) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if (strcmp(method, "publickey") != 0) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if (sshbuf_len(b) != 0) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ /* success */
+ r = 0;
+ debug3_f("well formed userauth");
+ if (userp != NULL) {
+ *userp = user;
+ user = NULL;
+ }
+ if (sess_idp != NULL) {
+ *sess_idp = sess_id;
+ sess_id = NULL;
+ }
+ out:
+ sshbuf_free(b);
+ sshbuf_free(sess_id);
+ free(user);
+ free(service);
+ free(method);
+ free(pkalg);
+ sshkey_free(mkey);
+ return r;
+}
+
+/*
+ * Attempt to parse the contents of a buffer as a SSHSIG signature request.
+ * Note: does not modify buffer.
+ */
+static int
+parse_sshsig_request(struct sshbuf *msg)
+{
+ int r;
+ struct sshbuf *b;
+
+ if ((b = sshbuf_fromb(msg)) == NULL)
+ fatal_f("sshbuf_fromb");
+
+ if ((r = sshbuf_cmp(b, 0, "SSHSIG", 6)) != 0 ||
+ (r = sshbuf_consume(b, 6)) != 0 ||
+ (r = sshbuf_get_cstring(b, NULL, NULL)) != 0 || /* namespace */
+ (r = sshbuf_get_string_direct(b, NULL, NULL)) != 0 || /* reserved */
+ (r = sshbuf_get_cstring(b, NULL, NULL)) != 0 || /* hashalg */
+ (r = sshbuf_get_string_direct(b, NULL, NULL)) != 0) /* H(msg) */
+ goto out;
+ if (sshbuf_len(b) != 0) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ /* success */
+ r = 0;
+ out:
+ sshbuf_free(b);
+ return r;
+}
+
+/*
+ * This function inspects a message to be signed by a FIDO key that has a
+ * web-like application string (i.e. one that does not begin with "ssh:".
+ * It checks that the message is one of those expected for SSH operations
+ * (pubkey userauth, sshsig, CA key signing) to exclude signing challenges
+ * for the web.
+ */
+static int
+check_websafe_message_contents(struct sshkey *key, struct sshbuf *data)
+{
+ if (parse_userauth_request(data, key, NULL, NULL) == 0) {
+ debug_f("signed data matches public key userauth request");
+ return 1;
+ }
+ if (parse_sshsig_request(data) == 0) {
+ debug_f("signed data matches SSHSIG signature request");
+ return 1;
+ }
+
+ /* XXX check CA signature operation */
+
+ error("web-origin key attempting to sign non-SSH message");
+ return 0;
+}
+
/* ssh2 only */
static void
process_sign_request2(SocketEntry *e)
{
- const u_char *data;
u_char *signature = NULL;
- size_t dlen, slen = 0;
+ size_t slen = 0;
u_int compat = 0, flags;
int r, ok = -1;
char *fp = NULL;
- struct sshbuf *msg;
+ struct sshbuf *msg = NULL, *data = NULL;
struct sshkey *key = NULL;
struct identity *id;
struct notifier_ctx *notifier = NULL;
- if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ debug_f("entering");
+
+ if ((msg = sshbuf_new()) == NULL || (data = sshbuf_new()) == NULL)
+ fatal_f("sshbuf_new failed");
if ((r = sshkey_froms(e->request, &key)) != 0 ||
- (r = sshbuf_get_string_direct(e->request, &data, &dlen)) != 0 ||
+ (r = sshbuf_get_stringb(e->request, data)) != 0 ||
(r = sshbuf_get_u32(e->request, &flags)) != 0) {
- error("%s: couldn't parse request: %s", __func__, ssh_err(r));
+ error_fr(r, "parse");
goto send;
}
if ((id = lookup_identity(key)) == NULL) {
- verbose("%s: %s key not found", __func__, sshkey_type(key));
+ verbose_f("%s key not found", sshkey_type(key));
goto send;
}
- if (id->confirm && confirm_key(id) != 0) {
- verbose("%s: user refused key", __func__);
+ if (id->confirm && confirm_key(id, NULL) != 0) {
+ verbose_f("user refused key");
goto send;
}
- if (sshkey_is_sk(id->key) &&
- (id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
- if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
- SSH_FP_DEFAULT)) == NULL)
- fatal("%s: fingerprint failed", __func__);
- notifier = notify_start(0,
- "Confirm user presence for key %s %s",
- sshkey_type(id->key), fp);
+ if (sshkey_is_sk(id->key)) {
+ if (strncmp(id->key->sk_application, "ssh:", 4) != 0 &&
+ !check_websafe_message_contents(key, data)) {
+ /* error already logged */
+ goto send;
+ }
+ if ((id->key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
+ if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
+ SSH_FP_DEFAULT)) == NULL)
+ fatal_f("fingerprint failed");
+ notifier = notify_start(0,
+ "Confirm user presence for key %s %s",
+ sshkey_type(id->key), fp);
+ }
}
+ /* XXX support PIN required FIDO keys */
if ((r = sshkey_sign(id->key, &signature, &slen,
- data, dlen, agent_decode_alg(key, flags),
- id->sk_provider, compat)) != 0) {
- error("%s: sshkey_sign: %s", __func__, ssh_err(r));
+ sshbuf_ptr(data), sshbuf_len(data), agent_decode_alg(key, flags),
+ id->sk_provider, NULL, compat)) != 0) {
+ error_fr(r, "sshkey_sign");
goto send;
}
/* Success */
ok = 0;
send:
- notify_complete(notifier);
- sshkey_free(key);
- free(fp);
+ notify_complete(notifier, "User presence confirmed");
+
if (ok == 0) {
if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 ||
(r = sshbuf_put_string(msg, signature, slen)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
} else if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose failure");
if ((r = sshbuf_put_stringb(e->output, msg)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "enqueue");
+ sshbuf_free(data);
sshbuf_free(msg);
+ sshkey_free(key);
+ free(fp);
free(signature);
}
@@ -357,24 +507,24 @@ process_remove_identity(SocketEntry *e)
struct sshkey *key = NULL;
Identity *id;
+ debug2_f("entering");
if ((r = sshkey_froms(e->request, &key)) != 0) {
- error("%s: get key: %s", __func__, ssh_err(r));
+ error_fr(r, "parse key");
goto done;
}
if ((id = lookup_identity(key)) == NULL) {
- debug("%s: key not found", __func__);
+ debug_f("key not found");
goto done;
}
/* We have this key, free it. */
if (idtab->nentries < 1)
- fatal("%s: internal error: nentries %d",
- __func__, idtab->nentries);
+ fatal_f("internal error: nentries %d", idtab->nentries);
TAILQ_REMOVE(&idtab->idlist, id, next);
free_identity(id);
idtab->nentries--;
- sshkey_free(key);
success = 1;
done:
+ sshkey_free(key);
send_status(e, success);
}
@@ -383,6 +533,7 @@ process_remove_all_identities(SocketEntry *e)
{
Identity *id;
+ debug2_f("entering");
/* Loop over all identities and clear the keys. */
for (id = TAILQ_FIRST(&idtab->idlist); id;
id = TAILQ_FIRST(&idtab->idlist)) {
@@ -423,125 +574,171 @@ reaper(void)
return (deadline - now);
}
-static void
-process_add_identity(SocketEntry *e)
+static int
+parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp)
{
- Identity *id;
- int success = 0, confirm = 0;
- u_int seconds = 0, maxsign;
- char *fp, *comment = NULL, *ext_name = NULL, *sk_provider = NULL;
- char canonical_provider[PATH_MAX];
- time_t death = 0;
- struct sshkey *k = NULL;
- u_char ctype;
- int r = SSH_ERR_INTERNAL_ERROR;
+ char *ext_name = NULL;
+ int r;
- if ((r = sshkey_private_deserialize(e->request, &k)) != 0 ||
- k == NULL ||
- (r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) {
- error("%s: decode private key: %s", __func__, ssh_err(r));
- goto err;
+ if ((r = sshbuf_get_cstring(m, &ext_name, NULL)) != 0) {
+ error_fr(r, "parse constraint extension");
+ goto out;
}
- while (sshbuf_len(e->request)) {
- if ((r = sshbuf_get_u8(e->request, &ctype)) != 0) {
- error("%s: buffer error: %s", __func__, ssh_err(r));
- goto err;
+ debug_f("constraint ext %s", ext_name);
+ if (strcmp(ext_name, "sk-provider@openssh.com") == 0) {
+ if (sk_providerp == NULL) {
+ error_f("%s not valid here", ext_name);
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if (*sk_providerp != NULL) {
+ error_f("%s already set", ext_name);
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if ((r = sshbuf_get_cstring(m, sk_providerp, NULL)) != 0) {
+ error_fr(r, "parse %s", ext_name);
+ goto out;
+ }
+ } else {
+ error_f("unsupported constraint \"%s\"", ext_name);
+ r = SSH_ERR_FEATURE_UNSUPPORTED;
+ goto out;
+ }
+ /* success */
+ r = 0;
+ out:
+ free(ext_name);
+ return r;
+}
+
+static int
+parse_key_constraints(struct sshbuf *m, struct sshkey *k, time_t *deathp,
+ u_int *secondsp, int *confirmp, char **sk_providerp)
+{
+ u_char ctype;
+ int r;
+ u_int seconds, maxsign = 0;
+
+ while (sshbuf_len(m)) {
+ if ((r = sshbuf_get_u8(m, &ctype)) != 0) {
+ error_fr(r, "parse constraint type");
+ goto out;
}
switch (ctype) {
case SSH_AGENT_CONSTRAIN_LIFETIME:
- if ((r = sshbuf_get_u32(e->request, &seconds)) != 0) {
- error("%s: bad lifetime constraint: %s",
- __func__, ssh_err(r));
- goto err;
+ if (*deathp != 0) {
+ error_f("lifetime already set");
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if ((r = sshbuf_get_u32(m, &seconds)) != 0) {
+ error_fr(r, "parse lifetime constraint");
+ goto out;
}
- death = monotime() + seconds;
+ *deathp = monotime() + seconds;
+ *secondsp = seconds;
break;
case SSH_AGENT_CONSTRAIN_CONFIRM:
- confirm = 1;
+ if (*confirmp != 0) {
+ error_f("confirm already set");
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ *confirmp = 1;
break;
case SSH_AGENT_CONSTRAIN_MAXSIGN:
- if ((r = sshbuf_get_u32(e->request, &maxsign)) != 0) {
- error("%s: bad maxsign constraint: %s",
- __func__, ssh_err(r));
- goto err;
+ if (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("%s: cannot enable maxsign: %s",
- __func__, ssh_err(r));
- goto err;
+ error_fr(r, "enable maxsign");
+ goto out;
}
break;
case SSH_AGENT_CONSTRAIN_EXTENSION:
- if ((r = sshbuf_get_cstring(e->request,
- &ext_name, NULL)) != 0) {
- error("%s: cannot parse extension: %s",
- __func__, ssh_err(r));
- goto err;
- }
- debug("%s: constraint ext %s", __func__, ext_name);
- if (strcmp(ext_name, "sk-provider@openssh.com") == 0) {
- if (sk_provider != NULL) {
- error("%s already set", ext_name);
- goto err;
- }
- if ((r = sshbuf_get_cstring(e->request,
- &sk_provider, NULL)) != 0) {
- error("%s: cannot parse %s: %s",
- __func__, ext_name, ssh_err(r));
- goto err;
- }
- } else {
- error("%s: unsupported constraint \"%s\"",
- __func__, ext_name);
- goto err;
- }
- free(ext_name);
+ if ((r = parse_key_constraint_extension(m,
+ sk_providerp)) != 0)
+ goto out; /* error already logged */
break;
default:
- error("%s: Unknown constraint %d", __func__, ctype);
- err:
- free(sk_provider);
- free(ext_name);
- sshbuf_reset(e->request);
- free(comment);
- sshkey_free(k);
- goto send;
+ error_f("Unknown constraint %d", ctype);
+ r = SSH_ERR_FEATURE_UNSUPPORTED;
+ goto out;
}
}
+ /* success */
+ r = 0;
+ out:
+ return r;
+}
+
+static void
+process_add_identity(SocketEntry *e)
+{
+ Identity *id;
+ int success = 0, confirm = 0;
+ char *fp, *comment = NULL, *sk_provider = NULL;
+ char canonical_provider[PATH_MAX];
+ time_t death = 0;
+ u_int seconds = 0;
+ struct sshkey *k = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ debug2_f("entering");
+ if ((r = sshkey_private_deserialize(e->request, &k)) != 0 ||
+ k == NULL ||
+ (r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) {
+ error_fr(r, "parse");
+ goto out;
+ }
+ if (parse_key_constraints(e->request, k, &death, &seconds, &confirm,
+ &sk_provider) != 0) {
+ error_f("failed to parse constraints");
+ sshbuf_reset(e->request);
+ goto out;
+ }
+
if (sk_provider != NULL) {
if (!sshkey_is_sk(k)) {
error("Cannot add provider: %s is not an "
"authenticator-hosted key", sshkey_type(k));
- free(sk_provider);
- goto send;
+ goto out;
}
if (strcasecmp(sk_provider, "internal") == 0) {
- debug("%s: internal provider", __func__);
+ debug_f("internal provider");
} else {
if (realpath(sk_provider, canonical_provider) == NULL) {
verbose("failed provider \"%.100s\": "
"realpath: %s", sk_provider,
strerror(errno));
- free(sk_provider);
- goto send;
+ goto out;
}
free(sk_provider);
sk_provider = xstrdup(canonical_provider);
if (match_pattern_list(sk_provider,
- provider_whitelist, 0) != 1) {
+ allowed_providers, 0) != 1) {
error("Refusing add key: "
- "provider %s not whitelisted", sk_provider);
- free(sk_provider);
- goto send;
+ "provider %s not allowed", sk_provider);
+ goto out;
}
}
}
if ((r = sshkey_shield_private(k)) != 0) {
- error("%s: shield private key: %s", __func__, ssh_err(r));
- goto err;
+ error_fr(r, "shield private");
+ goto out;
}
-
- success = 1;
if (lifetime && !death)
death = monotime() + lifetime;
if ((id = lookup_identity(k)) == NULL) {
@@ -555,6 +752,7 @@ process_add_identity(SocketEntry *e)
free(id->comment);
free(id->sk_provider);
}
+ /* success */
id->key = k;
id->comment = comment;
id->death = death;
@@ -563,12 +761,20 @@ process_add_identity(SocketEntry *e)
if ((fp = sshkey_fingerprint(k, SSH_FP_HASH_DEFAULT,
SSH_FP_DEFAULT)) == NULL)
- fatal("%s: sshkey_fingerprint failed", __func__);
- debug("%s: add %s %s \"%.100s\" (life: %u) (confirm: %u) "
- "(provider: %s)", __func__, sshkey_ssh_name(k), fp, comment,
- seconds, confirm, sk_provider == NULL ? "none" : sk_provider);
+ fatal_f("sshkey_fingerprint failed");
+ debug_f("add %s %s \"%.100s\" (life: %u) (confirm: %u) "
+ "(provider: %s)", sshkey_ssh_name(k), fp, comment, seconds,
+ confirm, sk_provider == NULL ? "none" : sk_provider);
free(fp);
-send:
+ /* transferred */
+ k = NULL;
+ comment = NULL;
+ sk_provider = NULL;
+ success = 1;
+ out:
+ free(sk_provider);
+ free(comment);
+ sshkey_free(k);
send_status(e, success);
}
@@ -582,13 +788,14 @@ process_lock_agent(SocketEntry *e, int lock)
static u_int fail_count = 0;
size_t pwlen;
+ debug2_f("entering");
/*
* This is deliberately fatal: the user has requested that we lock,
* but we can't parse their request properly. The only safe thing to
* do is abort.
*/
if ((r = sshbuf_get_cstring(e->request, &passwd, &pwlen)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (pwlen == 0) {
debug("empty password not supported");
} else if (locked && !lock) {
@@ -631,11 +838,11 @@ no_identities(SocketEntry *e)
int r;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
(r = sshbuf_put_u32(msg, 0)) != 0 ||
(r = sshbuf_put_stringb(e->output, msg)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
sshbuf_free(msg);
}
@@ -646,51 +853,33 @@ process_add_smartcard_key(SocketEntry *e)
char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX];
char **comments = NULL;
int r, i, count = 0, success = 0, confirm = 0;
- u_int seconds;
+ u_int seconds = 0;
time_t death = 0;
- u_char type;
struct sshkey **keys = NULL, *k;
Identity *id;
+ debug2_f("entering");
if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 ||
(r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) {
- error("%s: buffer error: %s", __func__, ssh_err(r));
+ error_fr(r, "parse");
goto send;
}
-
- while (sshbuf_len(e->request)) {
- if ((r = sshbuf_get_u8(e->request, &type)) != 0) {
- error("%s: buffer error: %s", __func__, ssh_err(r));
- goto send;
- }
- switch (type) {
- case SSH_AGENT_CONSTRAIN_LIFETIME:
- if ((r = sshbuf_get_u32(e->request, &seconds)) != 0) {
- error("%s: buffer error: %s",
- __func__, ssh_err(r));
- goto send;
- }
- death = monotime() + seconds;
- break;
- case SSH_AGENT_CONSTRAIN_CONFIRM:
- confirm = 1;
- break;
- default:
- error("%s: Unknown constraint type %d", __func__, type);
- goto send;
- }
+ if (parse_key_constraints(e->request, NULL, &death, &seconds, &confirm,
+ NULL) != 0) {
+ error_f("failed to parse constraints");
+ goto send;
}
if (realpath(provider, canonical_provider) == NULL) {
verbose("failed PKCS#11 add of \"%.100s\": realpath: %s",
provider, strerror(errno));
goto send;
}
- if (match_pattern_list(canonical_provider, provider_whitelist, 0) != 1) {
+ if (match_pattern_list(canonical_provider, allowed_providers, 0) != 1) {
verbose("refusing PKCS#11 add of \"%.100s\": "
- "provider not whitelisted", canonical_provider);
+ "provider not allowed", canonical_provider);
goto send;
}
- debug("%s: add %.100s", __func__, canonical_provider);
+ debug_f("add %.100s", canonical_provider);
if (lifetime && !death)
death = monotime() + lifetime;
@@ -714,6 +903,7 @@ process_add_smartcard_key(SocketEntry *e)
idtab->nentries++;
success = 1;
}
+ /* XXX update constraints for existing keys */
sshkey_free(keys[i]);
free(comments[i]);
}
@@ -732,9 +922,10 @@ process_remove_smartcard_key(SocketEntry *e)
int r, success = 0;
Identity *id, *nxt;
+ debug2_f("entering");
if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 ||
(r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) {
- error("%s: buffer error: %s", __func__, ssh_err(r));
+ error_fr(r, "parse");
goto send;
}
free(pin);
@@ -745,7 +936,7 @@ process_remove_smartcard_key(SocketEntry *e)
goto send;
}
- debug("%s: remove %.100s", __func__, canonical_provider);
+ debug_f("remove %.100s", canonical_provider);
for (id = TAILQ_FIRST(&idtab->idlist); id; id = nxt) {
nxt = TAILQ_NEXT(id, next);
/* Skip file--based keys */
@@ -760,15 +951,17 @@ process_remove_smartcard_key(SocketEntry *e)
if (pkcs11_del_provider(canonical_provider) == 0)
success = 1;
else
- error("%s: pkcs11_del_provider failed", __func__);
+ error_f("pkcs11_del_provider failed");
send:
free(provider);
send_status(e, success);
}
#endif /* ENABLE_PKCS11 */
-/* dispatch incoming messages */
-
+/*
+ * dispatch incoming message.
+ * returns 1 on success, 0 for incomplete messages or -1 on error.
+ */
static int
process_message(u_int socknum)
{
@@ -778,10 +971,8 @@ process_message(u_int socknum)
int r;
SocketEntry *e;
- if (socknum >= sockets_alloc) {
- fatal("%s: socket number %u >= allocated %u",
- __func__, socknum, sockets_alloc);
- }
+ if (socknum >= sockets_alloc)
+ fatal_f("sock %u >= allocated %u", socknum, sockets_alloc);
e = &sockets[socknum];
if (sshbuf_len(e->input) < 5)
@@ -789,8 +980,8 @@ process_message(u_int socknum)
cp = sshbuf_ptr(e->input);
msg_len = PEEK_U32(cp);
if (msg_len > AGENT_MAX_LEN) {
- debug("%s: socket %u (fd=%d) message too long %u > %u",
- __func__, socknum, e->fd, msg_len, AGENT_MAX_LEN);
+ debug_f("socket %u (fd=%d) message too long %u > %u",
+ socknum, e->fd, msg_len, AGENT_MAX_LEN);
return -1;
}
if (sshbuf_len(e->input) < msg_len + 4)
@@ -802,13 +993,13 @@ process_message(u_int socknum)
(r = sshbuf_get_u8(e->request, &type)) != 0) {
if (r == SSH_ERR_MESSAGE_INCOMPLETE ||
r == SSH_ERR_STRING_TOO_LARGE) {
- debug("%s: buffer error: %s", __func__, ssh_err(r));
+ error_fr(r, "parse");
return -1;
}
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
}
- debug("%s: socket %u (fd=%d) type %d", __func__, socknum, e->fd, type);
+ debug_f("socket %u (fd=%d) type %d", socknum, e->fd, type);
/* check whether agent is locked */
if (locked && type != SSH_AGENTC_UNLOCK) {
@@ -822,7 +1013,7 @@ process_message(u_int socknum)
/* send a fail message for all other request types */
send_status(e, 0);
}
- return 0;
+ return 1;
}
switch (type) {
@@ -866,7 +1057,7 @@ process_message(u_int socknum)
send_status(e, 0);
break;
}
- return 0;
+ return 1;
}
static void
@@ -874,6 +1065,8 @@ new_socket(sock_type type, int fd)
{
u_int i, old_alloc, new_alloc;
+ debug_f("type = %s", type == AUTH_CONNECTION ? "CONNECTION" :
+ (type == AUTH_SOCKET ? "SOCKET" : "UNKNOWN"));
set_nonblock(fd);
if (fd > max_fd)
@@ -882,28 +1075,25 @@ new_socket(sock_type type, int fd)
for (i = 0; i < sockets_alloc; i++)
if (sockets[i].type == AUTH_UNUSED) {
sockets[i].fd = fd;
- if ((sockets[i].input = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
- if ((sockets[i].output = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
- if ((sockets[i].request = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ if ((sockets[i].input = sshbuf_new()) == NULL ||
+ (sockets[i].output = sshbuf_new()) == NULL ||
+ (sockets[i].request = sshbuf_new()) == NULL)
+ fatal_f("sshbuf_new failed");
sockets[i].type = type;
return;
}
old_alloc = sockets_alloc;
new_alloc = sockets_alloc + 10;
- sockets = xreallocarray(sockets, new_alloc, sizeof(sockets[0]));
+ sockets = xrecallocarray(sockets, old_alloc, new_alloc,
+ sizeof(sockets[0]));
for (i = old_alloc; i < new_alloc; i++)
sockets[i].type = AUTH_UNUSED;
sockets_alloc = new_alloc;
sockets[old_alloc].fd = fd;
- if ((sockets[old_alloc].input = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
- if ((sockets[old_alloc].output = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
- if ((sockets[old_alloc].request = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ if ((sockets[old_alloc].input = sshbuf_new()) == NULL ||
+ (sockets[old_alloc].output = sshbuf_new()) == NULL ||
+ (sockets[old_alloc].request = sshbuf_new()) == NULL)
+ fatal_f("sshbuf_new failed");
sockets[old_alloc].type = type;
}
@@ -948,16 +1138,20 @@ handle_conn_read(u_int socknum)
if (len == -1) {
if (errno == EAGAIN || errno == EINTR)
return 0;
- error("%s: read error on socket %u (fd %d): %s",
- __func__, socknum, sockets[socknum].fd,
- strerror(errno));
+ error_f("read error on socket %u (fd %d): %s",
+ socknum, sockets[socknum].fd, strerror(errno));
}
return -1;
}
if ((r = sshbuf_put(sockets[socknum].input, buf, len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
explicit_bzero(buf, sizeof(buf));
- process_message(socknum);
+ for (;;) {
+ if ((r = process_message(socknum)) == -1)
+ return -1;
+ else if (r == 0)
+ break;
+ }
return 0;
}
@@ -975,14 +1169,13 @@ handle_conn_write(u_int socknum)
if (len == -1) {
if (errno == EAGAIN || errno == EINTR)
return 0;
- error("%s: read error on socket %u (fd %d): %s",
- __func__, socknum, sockets[socknum].fd,
- strerror(errno));
+ error_f("read error on socket %u (fd %d): %s",
+ socknum, sockets[socknum].fd, strerror(errno));
}
return -1;
}
if ((r = sshbuf_consume(sockets[socknum].output, len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "consume");
return 0;
}
@@ -1004,7 +1197,7 @@ after_poll(struct pollfd *pfd, size_t npfd, u_int maxfds)
break;
}
if (socknum >= sockets_alloc) {
- error("%s: no socket for fd %d", __func__, pfd[i].fd);
+ error_f("no socket for fd %d", pfd[i].fd);
continue;
}
/* Process events */
@@ -1065,7 +1258,7 @@ prepare_poll(struct pollfd **pfdp, size_t *npfdp, int *timeoutp, u_int maxfds)
}
if (npfd != *npfdp &&
(pfd = recallocarray(pfd, *npfdp, npfd, sizeof(*pfd))) == NULL)
- fatal("%s: recallocarray failed", __func__);
+ fatal_f("recallocarray failed");
*pfdp = pfd;
*npfdp = npfd;
@@ -1092,12 +1285,10 @@ prepare_poll(struct pollfd **pfdp, size_t *npfdp, int *timeoutp, u_int maxfds)
if ((r = sshbuf_check_reserve(sockets[i].input,
AGENT_RBUF_LEN)) == 0 &&
(r = sshbuf_check_reserve(sockets[i].output,
- AGENT_MAX_LEN)) == 0)
+ AGENT_MAX_LEN)) == 0)
pfd[j].events = POLLIN;
- else if (r != SSH_ERR_NO_BUFFER_SPACE) {
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
- }
+ else if (r != SSH_ERR_NO_BUFFER_SPACE)
+ fatal_fr(r, "reserve");
if (sshbuf_len(sockets[i].output) > 0)
pfd[j].events |= POLLOUT;
j++;
@@ -1126,7 +1317,7 @@ cleanup_socket(void)
{
if (cleanup_pid != 0 && getpid() != cleanup_pid)
return;
- debug("%s: cleanup", __func__);
+ debug_f("cleanup");
if (socket_name[0])
unlink(socket_name);
if (socket_dir[0])
@@ -1170,7 +1361,9 @@ usage(void)
{
fprintf(stderr,
"usage: ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash]\n"
- " [-P provider_whitelist] [-t life] [command [arg ...]]\n"
+ " [-P allowed_providers] [-t life]\n"
+ " ssh-agent [-a bind_address] [-E fingerprint_hash] [-P allowed_providers]\n"
+ " [-t life] command [arg ...]\n"
" ssh-agent [-c | -s] -k\n");
exit(1);
}
@@ -1179,7 +1372,7 @@ int
main(int ac, char **av)
{
int c_flag = 0, d_flag = 0, D_flag = 0, k_flag = 0, s_flag = 0;
- int sock, fd, ch, result, saved_errno;
+ int sock, ch, result, saved_errno;
char *shell, *format, *pidstr, *agentsocket = NULL;
#ifdef HAVE_SETRLIMIT
struct rlimit rlim;
@@ -1212,7 +1405,7 @@ main(int ac, char **av)
__progname = ssh_get_progname(av[0]);
seed_rng();
- while ((ch = getopt(ac, av, "cDdksE:a:P:t:")) != -1) {
+ while ((ch = getopt(ac, av, "cDdksE:a:O:P:t:")) != -1) {
switch (ch) {
case 'E':
fingerprint_hash = ssh_digest_alg_by_name(optarg);
@@ -1227,10 +1420,16 @@ main(int ac, char **av)
case 'k':
k_flag++;
break;
+ case 'O':
+ if (strcmp(optarg, "no-restrict-websafe") == 0)
+ restrict_websafe = 0;
+ else
+ fatal("Unknown -O option");
+ break;
case 'P':
- if (provider_whitelist != NULL)
+ if (allowed_providers != NULL)
fatal("-P option already specified");
- provider_whitelist = xstrdup(optarg);
+ allowed_providers = xstrdup(optarg);
break;
case 's':
if (c_flag)
@@ -1266,8 +1465,8 @@ main(int ac, char **av)
if (ac > 0 && (c_flag || k_flag || s_flag || d_flag || D_flag))
usage();
- if (provider_whitelist == NULL)
- provider_whitelist = xstrdup(DEFAULT_PROVIDER_WHITELIST);
+ if (allowed_providers == NULL)
+ allowed_providers = xstrdup(DEFAULT_ALLOWED_PROVIDERS);
if (ac == 0 && !c_flag && !s_flag) {
shell = getenv("SHELL");
@@ -1393,14 +1592,8 @@ main(int ac, char **av)
}
(void)chdir("/");
- if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
- /* XXX might close listen socket */
- (void)dup2(fd, STDIN_FILENO);
- (void)dup2(fd, STDOUT_FILENO);
- (void)dup2(fd, STDERR_FILENO);
- if (fd > 2)
- close(fd);
- }
+ if (stdfd_devnull(1, 1, 1) == -1)
+ error_f("stdfd_devnull failed");
#ifdef HAVE_SETRLIMIT
/* deny core dumps, since memory contains unencrypted private keys */
diff --git a/ssh-ecdsa-sk.c b/ssh-ecdsa-sk.c
index 981d60d74..c6927ecb2 100644
--- a/ssh-ecdsa-sk.c
+++ b/ssh-ecdsa-sk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ecdsa-sk.c,v 1.5 2019/11/26 03:04:27 djm Exp $ */
+/* $OpenBSD: ssh-ecdsa-sk.c,v 1.8 2020/06/22 23:44:27 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -49,6 +49,94 @@
#define SSHKEY_INTERNAL
#include "sshkey.h"
+#ifndef OPENSSL_HAS_ECC
+/* ARGSUSED */
+int
+ssh_ecdsa_sk_verify(const struct sshkey *key,
+ const u_char *signature, size_t signaturelen,
+ const u_char *data, size_t datalen, u_int compat,
+ struct sshkey_sig_details **detailsp)
+{
+ return SSH_ERR_FEATURE_UNSUPPORTED;
+}
+#else /* OPENSSL_HAS_ECC */
+
+/*
+ * Check FIDO/W3C webauthn signatures clientData field against the expected
+ * format and prepare a hash of it for use in signature verification.
+ *
+ * webauthn signatures do not sign the hash of the message directly, but
+ * instead sign a JSON-like "clientData" wrapper structure that contains the
+ * message hash along with a other information.
+ *
+ * Fortunately this structure has a fixed format so it is possible to verify
+ * that the hash of the signed message is present within the clientData
+ * structure without needing to implement any JSON parsing.
+ */
+static int
+webauthn_check_prepare_hash(const u_char *data, size_t datalen,
+ const char *origin, const struct sshbuf *wrapper,
+ uint8_t flags, const struct sshbuf *extensions,
+ u_char *msghash, size_t msghashlen)
+{
+ int r = SSH_ERR_INTERNAL_ERROR;
+ struct sshbuf *chall = NULL, *m = NULL;
+
+ if ((m = sshbuf_new()) == NULL ||
+ (chall = sshbuf_from(data, datalen)) == NULL) {
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ /*
+ * Ensure origin contains no quote character and that the flags are
+ * consistent with what we received
+ */
+ if (strchr(origin, '\"') != NULL ||
+ (flags & 0x40) != 0 /* AD */ ||
+ ((flags & 0x80) == 0 /* ED */) != (sshbuf_len(extensions) == 0)) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+
+ /*
+ * Prepare the preamble to clientData that we expect, poking the
+ * challenge and origin into their canonical positions in the
+ * structure. The crossOrigin flag and any additional extension
+ * fields present are ignored.
+ */
+#define WEBAUTHN_0 "{\"type\":\"webauthn.get\",\"challenge\":\""
+#define WEBAUTHN_1 "\",\"origin\":\""
+#define WEBAUTHN_2 "\""
+ if ((r = sshbuf_put(m, WEBAUTHN_0, sizeof(WEBAUTHN_0) - 1)) != 0 ||
+ (r = sshbuf_dtourlb64(chall, m, 0)) != 0 ||
+ (r = sshbuf_put(m, WEBAUTHN_1, sizeof(WEBAUTHN_1) - 1)) != 0 ||
+ (r = sshbuf_put(m, origin, strlen(origin))) != 0 ||
+ (r = sshbuf_put(m, WEBAUTHN_2, sizeof(WEBAUTHN_2) - 1)) != 0)
+ goto out;
+#ifdef DEBUG_SK
+ fprintf(stderr, "%s: received origin: %s\n", __func__, origin);
+ fprintf(stderr, "%s: received clientData:\n", __func__);
+ sshbuf_dump(wrapper, stderr);
+ fprintf(stderr, "%s: expected clientData premable:\n", __func__);
+ sshbuf_dump(m, stderr);
+#endif
+ /* Check that the supplied clientData has the preamble we expect */
+ if ((r = sshbuf_cmp(wrapper, 0, sshbuf_ptr(m), sshbuf_len(m))) != 0)
+ goto out;
+
+ /* Prepare hash of clientData */
+ if ((r = ssh_digest_buffer(SSH_DIGEST_SHA256, wrapper,
+ msghash, msghashlen)) != 0)
+ goto out;
+
+ /* success */
+ r = 0;
+ out:
+ sshbuf_free(chall);
+ sshbuf_free(m);
+ return r;
+}
+
/* ARGSUSED */
int
ssh_ecdsa_sk_verify(const struct sshkey *key,
@@ -56,15 +144,15 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
const u_char *data, size_t datalen, u_int compat,
struct sshkey_sig_details **detailsp)
{
-#ifdef OPENSSL_HAS_ECC
ECDSA_SIG *sig = NULL;
BIGNUM *sig_r = NULL, *sig_s = NULL;
u_char sig_flags;
u_char msghash[32], apphash[32], sighash[32];
u_int sig_counter;
- int ret = SSH_ERR_INTERNAL_ERROR;
+ int is_webauthn = 0, ret = SSH_ERR_INTERNAL_ERROR;
struct sshbuf *b = NULL, *sigbuf = NULL, *original_signed = NULL;
- char *ktype = NULL;
+ struct sshbuf *webauthn_wrapper = NULL, *webauthn_exts = NULL;
+ char *ktype = NULL, *webauthn_origin = NULL;
struct sshkey_sig_details *details = NULL;
#ifdef DEBUG_SK
char *tmp = NULL;
@@ -83,16 +171,33 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
/* fetch signature */
if ((b = sshbuf_from(signature, signaturelen)) == NULL)
return SSH_ERR_ALLOC_FAIL;
- if (sshbuf_get_cstring(b, &ktype, NULL) != 0 ||
- sshbuf_froms(b, &sigbuf) != 0 ||
+ if ((details = calloc(1, sizeof(*details))) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if (sshbuf_get_cstring(b, &ktype, NULL) != 0) {
+ ret = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if (strcmp(ktype, "webauthn-sk-ecdsa-sha2-nistp256@openssh.com") == 0)
+ is_webauthn = 1;
+ else if (strcmp(ktype, "sk-ecdsa-sha2-nistp256@openssh.com") != 0) {
+ ret = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if (sshbuf_froms(b, &sigbuf) != 0 ||
sshbuf_get_u8(b, &sig_flags) != 0 ||
sshbuf_get_u32(b, &sig_counter) != 0) {
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
- if (strcmp(sshkey_ssh_name_plain(key), ktype) != 0) {
- ret = SSH_ERR_KEY_TYPE_MISMATCH;
- goto out;
+ if (is_webauthn) {
+ if (sshbuf_get_cstring(b, &webauthn_origin, NULL) != 0 ||
+ sshbuf_froms(b, &webauthn_wrapper) != 0 ||
+ sshbuf_froms(b, &webauthn_exts) != 0) {
+ ret = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
}
if (sshbuf_len(b) != 0) {
ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
@@ -105,14 +210,11 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
- if ((sig = ECDSA_SIG_new()) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if (!ECDSA_SIG_set0(sig, sig_r, sig_s)) {
- ret = SSH_ERR_LIBCRYPTO_ERROR;
+ if (sshbuf_len(sigbuf) != 0) {
+ ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
goto out;
}
+
#ifdef DEBUG_SK
fprintf(stderr, "%s: data: (len %zu)\n", __func__, datalen);
/* sshbuf_dump_data(data, datalen, stderr); */
@@ -122,20 +224,34 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
free(tmp);
fprintf(stderr, "%s: sig_flags = 0x%02x, sig_counter = %u\n",
__func__, sig_flags, sig_counter);
+ if (is_webauthn) {
+ fprintf(stderr, "%s: webauthn origin: %s\n", __func__,
+ webauthn_origin);
+ fprintf(stderr, "%s: webauthn_wrapper:\n", __func__);
+ sshbuf_dump(webauthn_wrapper, stderr);
+ }
#endif
- sig_r = sig_s = NULL; /* transferred */
-
- if (sshbuf_len(sigbuf) != 0) {
- ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
+ if ((sig = ECDSA_SIG_new()) == NULL) {
+ ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
+ if (!ECDSA_SIG_set0(sig, sig_r, sig_s)) {
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
+ goto out;
+ }
+ sig_r = sig_s = NULL; /* transferred */
/* Reconstruct data that was supposedly signed */
if ((original_signed = sshbuf_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
}
- if ((ret = ssh_digest_memory(SSH_DIGEST_SHA256, data, datalen,
+ if (is_webauthn) {
+ if ((ret = webauthn_check_prepare_hash(data, datalen,
+ webauthn_origin, webauthn_wrapper, sig_flags, webauthn_exts,
+ msghash, sizeof(msghash))) != 0)
+ goto out;
+ } else if ((ret = ssh_digest_memory(SSH_DIGEST_SHA256, data, datalen,
msghash, sizeof(msghash))) != 0)
goto out;
/* Application value is hashed before signature */
@@ -152,16 +268,13 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
apphash, sizeof(apphash))) != 0 ||
(ret = sshbuf_put_u8(original_signed, sig_flags)) != 0 ||
(ret = sshbuf_put_u32(original_signed, sig_counter)) != 0 ||
+ (ret = sshbuf_putb(original_signed, webauthn_exts)) != 0 ||
(ret = sshbuf_put(original_signed, msghash, sizeof(msghash))) != 0)
goto out;
/* Signature is over H(original_signed) */
if ((ret = ssh_digest_buffer(SSH_DIGEST_SHA256, original_signed,
sighash, sizeof(sighash))) != 0)
goto out;
- if ((details = calloc(1, sizeof(*details))) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
details->sk_counter = sig_counter;
details->sk_flags = sig_flags;
#ifdef DEBUG_SK
@@ -195,6 +308,9 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
explicit_bzero(sighash, sizeof(msghash));
explicit_bzero(apphash, sizeof(apphash));
sshkey_sig_details_free(details);
+ sshbuf_free(webauthn_wrapper);
+ sshbuf_free(webauthn_exts);
+ free(webauthn_origin);
sshbuf_free(original_signed);
sshbuf_free(sigbuf);
sshbuf_free(b);
@@ -203,7 +319,6 @@ ssh_ecdsa_sk_verify(const struct sshkey *key,
BN_clear_free(sig_s);
free(ktype);
return ret;
-#else
- return SSH_ERR_INTERNAL_ERROR;
-#endif
}
+
+#endif /* OPENSSL_HAS_ECC */
diff --git a/ssh-ed25519-sk.c b/ssh-ed25519-sk.c
index f784776d4..4393ca669 100644
--- a/ssh-ed25519-sk.c
+++ b/ssh-ed25519-sk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ed25519-sk.c,v 1.5 2020/02/26 13:40:09 jsg Exp $ */
+/* $OpenBSD: ssh-ed25519-sk.c,v 1.6 2020/10/18 11:32:02 djm Exp $ */
/*
* Copyright (c) 2019 Markus Friedl. All rights reserved.
*
@@ -139,8 +139,7 @@ ssh_ed25519_sk_verify(const struct sshkey *key,
}
if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen,
key->ed25519_pk)) != 0) {
- debug2("%s: crypto_sign_ed25519_open failed: %d",
- __func__, ret);
+ debug2_f("crypto_sign_ed25519_open failed: %d", ret);
}
if (ret != 0 || mlen != smlen - len) {
r = SSH_ERR_SIGNATURE_INVALID;
diff --git a/ssh-ed25519.c b/ssh-ed25519.c
index 7dee82707..23419f3c8 100644
--- a/ssh-ed25519.c
+++ b/ssh-ed25519.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-ed25519.c,v 1.8 2020/02/26 13:40:09 jsg Exp $ */
+/* $OpenBSD: ssh-ed25519.c,v 1.9 2020/10/18 11:32:02 djm Exp $ */
/*
* Copyright (c) 2013 Markus Friedl <markus@openbsd.org>
*
@@ -140,8 +140,7 @@ ssh_ed25519_verify(const struct sshkey *key,
memcpy(sm+len, data, datalen);
if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen,
key->ed25519_pk)) != 0) {
- debug2("%s: crypto_sign_ed25519_open failed: %d",
- __func__, ret);
+ debug2_f("crypto_sign_ed25519_open failed: %d", ret);
}
if (ret != 0 || mlen != datalen) {
r = SSH_ERR_SIGNATURE_INVALID;
diff --git a/ssh-gss.h b/ssh-gss.h
index 36180d07a..a8af117d2 100644
--- a/ssh-gss.h
+++ b/ssh-gss.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-gss.h,v 1.14 2018/07/10 09:13:30 djm Exp $ */
+/* $OpenBSD: ssh-gss.h,v 1.15 2021/01/27 10:05:28 djm Exp $ */
/*
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
*
@@ -122,7 +122,7 @@ void ssh_gssapi_build_ctx(Gssctxt **);
void ssh_gssapi_delete_ctx(Gssctxt **);
OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
void ssh_gssapi_buildmic(struct sshbuf *, const char *,
- const char *, const char *);
+ const char *, const char *, const struct sshbuf *);
int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *);
/* In the server */
diff --git a/ssh-keygen.1 b/ssh-keygen.1
index 059c1b034..f83f515f6 100644
--- a/ssh-keygen.1
+++ b/ssh-keygen.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ssh-keygen.1,v 1.203 2020/04/03 02:26:56 djm Exp $
+.\" $OpenBSD: ssh-keygen.1,v 1.216 2021/08/11 08:54:17 djm Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, 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: April 3 2020 $
+.Dd $Mdocdate: August 11 2021 $
.Dt SSH-KEYGEN 1
.Os
.Sh NAME
@@ -44,20 +44,24 @@
.Sh SYNOPSIS
.Nm ssh-keygen
.Op Fl q
+.Op Fl a Ar rounds
.Op Fl b Ar bits
.Op Fl C Ar comment
.Op Fl f Ar output_keyfile
.Op Fl m Ar format
-.Op Fl t Cm dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa
.Op Fl N Ar new_passphrase
.Op Fl O Ar option
+.Op Fl t Cm dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa
.Op Fl w Ar provider
+.Op Fl Z Ar cipher
.Nm ssh-keygen
.Fl p
+.Op Fl a Ar rounds
.Op Fl f Ar keyfile
.Op Fl m Ar format
.Op Fl N Ar new_passphrase
.Op Fl P Ar old_passphrase
+.Op Fl Z Ar cipher
.Nm ssh-keygen
.Fl i
.Op Fl f Ar input_keyfile
@@ -71,6 +75,7 @@
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl c
+.Op Fl a Ar rounds
.Op Fl C Ar comment
.Op Fl f Ar keyfile
.Op Fl P Ar passphrase
@@ -93,6 +98,7 @@
.Op Fl f Ar known_hosts_file
.Nm ssh-keygen
.Fl K
+.Op Fl a Ar rounds
.Op Fl w Ar provider
.Nm ssh-keygen
.Fl R Ar hostname
@@ -125,6 +131,7 @@
.Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl A
+.Op Fl a Ar rounds
.Op Fl f Ar prefix_path
.Nm ssh-keygen
.Fl k
@@ -140,10 +147,12 @@
.Ar
.Nm ssh-keygen
.Fl Y Cm find-principals
+.Op Fl O Ar option
.Fl s Ar signature_file
.Fl f Ar allowed_signers_file
.Nm ssh-keygen
.Fl Y Cm check-novalidate
+.Op Fl O Ar option
.Fl n Ar namespace
.Fl s Ar signature_file
.Nm ssh-keygen
@@ -153,6 +162,7 @@
.Ar
.Nm ssh-keygen
.Fl Y Cm verify
+.Op Fl O Ar option
.Fl f Ar allowed_signers_file
.Fl I Ar signer_identity
.Fl n Ar namespace
@@ -248,7 +258,9 @@ keys may be converted using this option in conjunction with the
.Fl p
(change passphrase) flag.
.Pp
-After a key is generated, instructions below detail where the keys
+After a key is generated,
+.Nm
+will ask where the keys
should be placed to be activated.
.Pp
The options are as follows:
@@ -267,9 +279,12 @@ This is used by
to generate new host keys.
.It Fl a Ar rounds
When saving a private key, this option specifies the number of KDF
-(key derivation function) rounds used.
+(key derivation function, currently
+.Xr bcrypt_pbkdf 3 )
+rounds used.
Higher numbers result in slower passphrase verification and increased
resistance to brute-force password cracking (should the keys be stolen).
+The default is 16 rounds.
.It Fl B
Show the bubblebabble digest of specified private or public key file.
.It Fl b Ar bits
@@ -374,6 +389,8 @@ The default import format is
Download resident keys from a FIDO authenticator.
Public and private key files will be written to the current directory for
each downloaded key.
+If multiple FIDO authenticators are attached, keys will be downloaded from
+the first touched authenticator.
.It Fl k
Generate a KRL file.
In this mode,
@@ -503,10 +520,30 @@ A username to be associated with a resident key,
overriding the empty default username.
Specifying a username may be useful when generating multiple resident keys
for the same application name.
+.It Cm verify-required
+Indicate that this private key should require user verification for
+each signature.
+Not all FIDO tokens support this option.
+Currently PIN authentication is the only supported verification method,
+but other methods may be supported in the future.
.It Cm write-attestation Ns = Ns Ar path
-May be used at key generation time to record the attestation certificate
+May be used at key generation time to record the attestation data
returned from FIDO tokens during key generation.
-By default this information is discarded.
+Please note that this information is potentially sensitive.
+By default, this information is discarded.
+.El
+.Pp
+When performing signature-related options using the
+.Fl Y
+flag, the following options are accepted:
+.Bl -tag -width Ds
+.It Cm print-pubkey
+Print the full public key to standard output after signature verification.
+.It Cm verify-time Ns = Ns Ar timestamp
+Specifies a time to use when validating signatures instead of the current
+time.
+The time may be specified as a date in YYYYMMDD format or a time
+in YYYYMMDDHHMM[SS] format.
.El
.Pp
The
@@ -617,7 +654,7 @@ For example:
.Dq 20100101123000:20110101123000
(valid from 12:30 PM, January 1st, 2010 to 12:30 PM, January 1st, 2011),
.Dq -1d:20110101
-(valid from yesterday to midnight, January 1st, 2011).
+(valid from yesterday to midnight, January 1st, 2011),
.Dq -1m:forever
(valid from one minute ago and never expiring).
.It Fl v
@@ -721,6 +758,13 @@ returning a zero exit status.
.It Fl y
This option will read a private
OpenSSH format file and print an OpenSSH public key to stdout.
+.It Fl Z Ar cipher
+Specifies the cipher to use for encryption when writing an OpenSSH-format
+private key file.
+The list of available ciphers may be obtained using
+.Qq ssh -Q cipher .
+The default is
+.Dq aes256-ctr .
.It Fl z Ar serial_number
Specifies a serial number to be embedded in the certificate to distinguish
this certificate from others from the same CA.
@@ -788,8 +832,7 @@ Valid generator values are 2, 3, and 5.
.Pp
Screened DH groups may be installed in
.Pa /etc/moduli .
-It is important that this file contains moduli of a range of bit lengths and
-that both ends of a connection share common moduli.
+It is important that this file contains moduli of a range of bit lengths.
.Pp
A number of options are available for moduli generation and screening via the
.Fl O
@@ -953,7 +996,7 @@ by
Allows X11 forwarding.
.Pp
.It Ic no-touch-required
-Do not require signatures made using this key require demonstration
+Do not require signatures made using this key include demonstration
of user presence (e.g. by having the user touch the authenticator).
This option only makes sense for the FIDO authenticator algorithms
.Cm ecdsa-sk
@@ -966,6 +1009,16 @@ The
.Ar address_list
is a comma-separated list of one or more address/netmask pairs in CIDR
format.
+.Pp
+.It Ic verify-required
+Require signatures made using this key indicate that the user was first
+verified.
+This option only makes sense for the FIDO authenticator algorithms
+.Cm ecdsa-sk
+and
+.Cm ed25519-sk .
+Currently PIN authentication is the only supported verification method,
+but other methods may be supported in the future.
.El
.Pp
At present, no standard options are valid for host keys.
@@ -976,7 +1029,7 @@ The
option allows specification of certificate start and end times.
A certificate that is presented at a time outside this range will not be
considered valid.
-By default, certificates are valid from
+By default, certificates are valid from the
.Ux
Epoch to the distant future.
.Pp
@@ -1080,7 +1133,7 @@ Empty lines and lines starting with a
.Ql #
are ignored as comments.
.Pp
-The principals field is a pattern-list (See PATTERNS in
+The principals field is a pattern-list (see PATTERNS in
.Xr ssh_config 5 )
consisting of one or more comma-separated USER@DOMAIN identity patterns
that are accepted for signing.
@@ -1097,11 +1150,16 @@ are case-insensitive):
.It Cm cert-authority
Indicates that this key is accepted as a certificate authority (CA) and
that certificates signed by this CA may be accepted for verification.
-.It Cm namespaces="namespace-list"
+.It Cm namespaces Ns = Ns "namespace-list"
Specifies a pattern-list of namespaces that are accepted for this key.
If this option is present, the signature namespace embedded in the
signature object and presented on the verification command-line must
match the specified list before the key will be considered acceptable.
+.It Cm valid-after Ns = Ns "timestamp"
+Indicates that the key is valid for use at or after the specified timestamp,
+which may be a date in YYYYMMDD format or a time in YYYYMMDDHHMM[SS] format.
+.It Cm valid-before Ns = Ns "timestamp"
+Indicates that the key is valid for use at or before the specified timestamp.
.El
.Pp
When verifying signatures made by certificates, the expected principal
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 2c5c75db7..4b40768d5 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keygen.c,v 1.409.2.1 2020/05/18 19:02:13 benno Exp $ */
+/* $OpenBSD: ssh-keygen.c,v 1.437 2021/09/08 03:23:44 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -65,6 +65,7 @@
#include "sshsig.h"
#include "ssh-sk.h"
#include "sk-api.h" /* XXX for SSH_SK_USER_PRESENCE_REQD; remove */
+#include "cipher.h"
#ifdef WITH_OPENSSL
# define DEFAULT_KEY_TYPE_NAME "rsa"
@@ -133,13 +134,13 @@ static char *certflags_command = NULL;
static char *certflags_src_addr = NULL;
/* Arbitrary extensions specified by user */
-struct cert_userext {
+struct cert_ext {
char *key;
char *val;
int crit;
};
-static struct cert_userext *cert_userext;
-static size_t ncert_userext;
+static struct cert_ext *cert_ext;
+static size_t ncert_ext;
/* Conversion to/from various formats */
enum {
@@ -184,7 +185,7 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp)
fatal("unknown key type %s", key_type_name);
if (*bitsp == 0) {
#ifdef WITH_OPENSSL
- u_int nid;
+ int nid;
switch(type) {
case KEY_DSA:
@@ -219,10 +220,11 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp)
break;
case KEY_ECDSA:
if (sshkey_ecdsa_bits_to_nid(*bitsp) == -1)
- fatal("Invalid ECDSA key length: valid lengths are "
#ifdef OPENSSL_HAS_NISTP521
+ fatal("Invalid ECDSA key length: valid lengths are "
"256, 384 or 521 bits");
#else
+ fatal("Invalid ECDSA key length: valid lengths are "
"256 or 384 bits");
#endif
}
@@ -321,7 +323,7 @@ load_identity(const char *filename, char **commentp)
if ((r = sshkey_load_private(filename, "", &prv, commentp)) == 0)
return prv;
if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)
- fatal("Load key \"%s\": %s", filename, ssh_err(r));
+ fatal_r(r, "Load key \"%s\"", filename);
if (identity_passphrase)
pass = xstrdup(identity_passphrase);
else
@@ -329,7 +331,7 @@ load_identity(const char *filename, char **commentp)
r = sshkey_load_private(filename, pass, &prv, commentp);
freezero(pass, strlen(pass));
if (r != 0)
- fatal("Load key \"%s\": %s", filename, ssh_err(r));
+ fatal_r(r, "Load key \"%s\"", filename);
return prv;
}
@@ -347,11 +349,11 @@ do_convert_to_ssh2(struct passwd *pw, struct sshkey *k)
int r;
if ((b = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshkey_putb(k, b)) != 0)
- fatal("key_to_blob failed: %s", ssh_err(r));
+ fatal_fr(r, "put key");
if ((b64 = sshbuf_dtob64_string(b, 1)) == NULL)
- fatal("%s: sshbuf_dtob64_string failed", __func__);
+ fatal_f("sshbuf_dtob64_string failed");
/* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */
snprintf(comment, sizeof(comment),
@@ -388,7 +390,7 @@ do_convert_to_pkcs8(struct sshkey *k)
break;
#endif
default:
- fatal("%s: unsupported key type %s", __func__, sshkey_type(k));
+ fatal_f("unsupported key type %s", sshkey_type(k));
}
exit(0);
}
@@ -412,7 +414,7 @@ do_convert_to_pem(struct sshkey *k)
break;
#endif
default:
- fatal("%s: unsupported key type %s", __func__, sshkey_type(k));
+ fatal_f("unsupported key type %s", sshkey_type(k));
}
exit(0);
}
@@ -441,7 +443,7 @@ do_convert_to(struct passwd *pw)
do_convert_to_pem(k);
break;
default:
- fatal("%s: unknown key format %d", __func__, convert_format);
+ fatal_f("unknown key format %d", convert_format);
}
exit(0);
}
@@ -457,15 +459,15 @@ buffer_get_bignum_bits(struct sshbuf *b, BIGNUM *value)
int r;
if ((r = sshbuf_get_u32(b, &bignum_bits)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
bytes = (bignum_bits + 7) / 8;
if (sshbuf_len(b) < bytes)
- fatal("%s: input buffer too small: need %d have %zu",
- __func__, bytes, sshbuf_len(b));
+ fatal_f("input buffer too small: need %d have %zu",
+ bytes, sshbuf_len(b));
if (BN_bin2bn(sshbuf_ptr(b), bytes, value) == NULL)
- fatal("%s: BN_bin2bn failed", __func__);
+ fatal_f("BN_bin2bn failed");
if ((r = sshbuf_consume(b, bytes)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "consume");
}
static struct sshkey *
@@ -484,7 +486,7 @@ do_convert_private_ssh2(struct sshbuf *b)
BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL;
if ((r = sshbuf_get_u32(b, &magic)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse magic");
if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
error("bad magic 0x%x != 0x%x", magic,
@@ -497,7 +499,7 @@ do_convert_private_ssh2(struct sshbuf *b)
(r = sshbuf_get_u32(b, &i2)) != 0 ||
(r = sshbuf_get_u32(b, &i3)) != 0 ||
(r = sshbuf_get_u32(b, &i4)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
debug("ignore (%d %d %d %d)", i1, i2, i3, i4);
if (strcmp(cipher, "none") != 0) {
error("unsupported cipher %s", cipher);
@@ -526,24 +528,24 @@ do_convert_private_ssh2(struct sshbuf *b)
(dsa_g = BN_new()) == NULL ||
(dsa_pub_key = BN_new()) == NULL ||
(dsa_priv_key = BN_new()) == NULL)
- fatal("%s: BN_new", __func__);
+ fatal_f("BN_new");
buffer_get_bignum_bits(b, dsa_p);
buffer_get_bignum_bits(b, dsa_g);
buffer_get_bignum_bits(b, dsa_q);
buffer_get_bignum_bits(b, dsa_pub_key);
buffer_get_bignum_bits(b, dsa_priv_key);
if (!DSA_set0_pqg(key->dsa, dsa_p, dsa_q, dsa_g))
- fatal("%s: DSA_set0_pqg failed", __func__);
+ fatal_f("DSA_set0_pqg failed");
dsa_p = dsa_q = dsa_g = NULL; /* transferred */
if (!DSA_set0_key(key->dsa, dsa_pub_key, dsa_priv_key))
- fatal("%s: DSA_set0_key failed", __func__);
+ fatal_f("DSA_set0_key failed");
dsa_pub_key = dsa_priv_key = NULL; /* transferred */
break;
case KEY_RSA:
if ((r = sshbuf_get_u8(b, &e1)) != 0 ||
(e1 < 30 && (r = sshbuf_get_u8(b, &e2)) != 0) ||
(e1 < 30 && (r = sshbuf_get_u8(b, &e3)) != 0))
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse RSA");
e = e1;
debug("e %lx", e);
if (e < 30) {
@@ -555,7 +557,7 @@ do_convert_private_ssh2(struct sshbuf *b)
debug("e %lx", e);
}
if ((rsa_e = BN_new()) == NULL)
- fatal("%s: BN_new", __func__);
+ fatal_f("BN_new");
if (!BN_set_word(rsa_e, e)) {
BN_clear_free(rsa_e);
sshkey_free(key);
@@ -566,30 +568,30 @@ do_convert_private_ssh2(struct sshbuf *b)
(rsa_p = BN_new()) == NULL ||
(rsa_q = BN_new()) == NULL ||
(rsa_iqmp = BN_new()) == NULL)
- fatal("%s: BN_new", __func__);
+ fatal_f("BN_new");
buffer_get_bignum_bits(b, rsa_d);
buffer_get_bignum_bits(b, rsa_n);
buffer_get_bignum_bits(b, rsa_iqmp);
buffer_get_bignum_bits(b, rsa_q);
buffer_get_bignum_bits(b, rsa_p);
if (!RSA_set0_key(key->rsa, rsa_n, rsa_e, rsa_d))
- fatal("%s: RSA_set0_key failed", __func__);
+ fatal_f("RSA_set0_key failed");
rsa_n = rsa_e = rsa_d = NULL; /* transferred */
if (!RSA_set0_factors(key->rsa, rsa_p, rsa_q))
- fatal("%s: RSA_set0_factors failed", __func__);
+ fatal_f("RSA_set0_factors failed");
rsa_p = rsa_q = NULL; /* transferred */
if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0)
- fatal("generate RSA parameters failed: %s", ssh_err(r));
+ fatal_fr(r, "generate RSA parameters");
BN_clear_free(rsa_iqmp);
break;
}
rlen = sshbuf_len(b);
if (rlen != 0)
- error("%s: remaining bytes in key blob %d", __func__, rlen);
+ error_f("remaining bytes in key blob %d", rlen);
/* try the key */
if (sshkey_sign(key, &sig, &slen, data, sizeof(data),
- NULL, NULL, 0) != 0 ||
+ NULL, NULL, NULL, 0) != 0 ||
sshkey_verify(key, sig, slen, data, sizeof(data),
NULL, 0, NULL) != 0) {
sshkey_free(key);
@@ -668,12 +670,12 @@ do_convert_from_ssh2(struct passwd *pw, struct sshkey **k, int *private)
(encoded[len-3] == '='))
encoded[len-3] = '\0';
if ((r = sshbuf_b64tod(buf, encoded)) != 0)
- fatal("%s: base64 decoding failed: %s", __func__, ssh_err(r));
+ fatal_fr(r, "base64 decode");
if (*private) {
if ((*k = do_convert_private_ssh2(buf)) == NULL)
- fatal("%s: private key conversion failed", __func__);
+ fatal_f("private key conversion failed");
} else if ((r = sshkey_fromb(buf, k)) != 0)
- fatal("decode blob failed: %s", ssh_err(r));
+ fatal_fr(r, "parse key");
sshbuf_free(buf);
fclose(fp);
}
@@ -687,7 +689,7 @@ do_convert_from_pkcs8(struct sshkey **k, int *private)
if ((fp = fopen(identity_file, "r")) == NULL)
fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
if ((pubkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
- fatal("%s: %s is not a recognised public key format", __func__,
+ fatal_f("%s is not a recognised public key format",
identity_file);
}
fclose(fp);
@@ -714,7 +716,7 @@ do_convert_from_pkcs8(struct sshkey **k, int *private)
break;
#endif
default:
- fatal("%s: unsupported pubkey type %d", __func__,
+ fatal_f("unsupported pubkey type %d",
EVP_PKEY_base_id(pubkey));
}
EVP_PKEY_free(pubkey);
@@ -737,7 +739,7 @@ do_convert_from_pem(struct sshkey **k, int *private)
fclose(fp);
return;
}
- fatal("%s: unrecognised raw private key format", __func__);
+ fatal_f("unrecognised raw private key format");
}
static void
@@ -763,7 +765,7 @@ do_convert_from(struct passwd *pw)
do_convert_from_pem(&k, &private);
break;
default:
- fatal("%s: unknown key format %d", __func__, convert_format);
+ fatal_f("unknown key format %d", convert_format);
}
if (!private) {
@@ -788,8 +790,7 @@ do_convert_from(struct passwd *pw)
NULL, 0, NULL, NULL);
break;
default:
- fatal("%s: unsupported key type %s", __func__,
- sshkey_type(k));
+ fatal_f("unsupported key type %s", sshkey_type(k));
}
}
@@ -814,11 +815,15 @@ do_print_public(struct passwd *pw)
fatal("%s: %s", identity_file, strerror(errno));
prv = load_identity(identity_file, &comment);
if ((r = sshkey_write(prv, stdout)) != 0)
- error("sshkey_write failed: %s", ssh_err(r));
- sshkey_free(prv);
+ fatal_fr(r, "write key");
if (comment != NULL && *comment != '\0')
fprintf(stdout, " %s", comment);
fprintf(stdout, "\n");
+ if (sshkey_is_sk(prv)) {
+ debug("sk_application: \"%s\", sk_flags 0x%02x",
+ prv->sk_application, prv->sk_flags);
+ }
+ sshkey_free(prv);
free(comment);
exit(0);
}
@@ -846,7 +851,7 @@ do_download(struct passwd *pw)
ra = sshkey_fingerprint(keys[i], fingerprint_hash,
SSH_FP_RANDOMART);
if (fp == NULL || ra == NULL)
- fatal("%s: sshkey_fingerprint fail", __func__);
+ fatal_f("sshkey_fingerprint fail");
printf("%u %s %s (PKCS11 key)\n", sshkey_size(keys[i]),
fp, sshkey_type(keys[i]));
if (log_level_get() >= SYSLOG_LEVEL_VERBOSE)
@@ -897,7 +902,7 @@ fingerprint_one_key(const struct sshkey *public, const char *comment)
fp = sshkey_fingerprint(public, fptype, rep);
ra = sshkey_fingerprint(public, fingerprint_hash, SSH_FP_RANDOMART);
if (fp == NULL || ra == NULL)
- fatal("%s: sshkey_fingerprint failed", __func__);
+ fatal_f("sshkey_fingerprint failed");
mprintf("%u %s %s (%s)\n", sshkey_size(public), fp,
comment ? comment : "no comment", sshkey_type(public));
if (log_level_get() >= SYSLOG_LEVEL_VERBOSE)
@@ -917,12 +922,12 @@ fingerprint_private(const char *path)
if (stat(identity_file, &st) == -1)
fatal("%s: %s", path, strerror(errno));
if ((r = sshkey_load_public(path, &pubkey, &comment)) != 0)
- debug("load public \"%s\": %s", path, ssh_err(r));
+ debug_r(r, "load public \"%s\"", path);
if (pubkey == NULL || comment == NULL || *comment == '\0') {
free(comment);
if ((r = sshkey_load_private(path, NULL,
&privkey, &comment)) != 0)
- debug("load private \"%s\": %s", path, ssh_err(r));
+ debug_r(r, "load private \"%s\"", path);
}
if (pubkey == NULL && privkey == NULL)
fatal("%s is not a key file.", path);
@@ -1102,18 +1107,17 @@ do_gen_all_hostkeys(struct passwd *pw)
bits = 0;
type_bits_valid(type, NULL, &bits);
if ((r = sshkey_generate(type, bits, &private)) != 0) {
- error("sshkey_generate failed: %s", ssh_err(r));
+ error_r(r, "sshkey_generate failed");
goto failnext;
}
if ((r = sshkey_from_private(private, &public)) != 0)
- fatal("sshkey_from_private failed: %s", ssh_err(r));
+ fatal_fr(r, "sshkey_from_private");
snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
hostname);
if ((r = sshkey_save_private(private, prv_tmp, "",
comment, private_key_format, openssh_format_cipher,
rounds)) != 0) {
- error("Saving key \"%s\" failed: %s",
- prv_tmp, ssh_err(r));
+ error_r(r, "Saving key \"%s\" failed", prv_tmp);
goto failnext;
}
if ((fd = mkstemp(pub_tmp)) == -1) {
@@ -1124,8 +1128,8 @@ do_gen_all_hostkeys(struct passwd *pw)
(void)fchmod(fd, 0644);
(void)close(fd);
if ((r = sshkey_save_public(public, pub_tmp, comment)) != 0) {
- fatal("Unable to save public key to %s: %s",
- identity_file, ssh_err(r));
+ error_r(r, "Unable to save public key to %s",
+ identity_file);
goto failnext;
}
@@ -1259,8 +1263,7 @@ known_hosts_find_delete(struct hostkey_foreach_line *l, void *_ctx)
ra = sshkey_fingerprint(l->key,
fingerprint_hash, SSH_FP_RANDOMART);
if (fp == NULL || ra == NULL)
- fatal("%s: sshkey_fingerprint failed",
- __func__);
+ fatal_f("sshkey_fingerprint failed");
mprintf("%s %s %s%s%s\n", ctx->host,
sshkey_type(l->key), fp,
l->comment[0] ? " " : "",
@@ -1292,6 +1295,7 @@ do_known_hosts(struct passwd *pw, const char *name, int find_host,
int r, fd, oerrno, inplace = 0;
struct known_hosts_ctx ctx;
u_int foreach_options;
+ struct stat sb;
if (!have_identity) {
cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);
@@ -1301,6 +1305,8 @@ do_known_hosts(struct passwd *pw, const char *name, int find_host,
free(cp);
have_identity = 1;
}
+ if (stat(identity_file, &sb) != 0)
+ fatal("Cannot stat %s: %s", identity_file, strerror(errno));
memset(&ctx, 0, sizeof(ctx));
ctx.out = stdout;
@@ -1327,6 +1333,7 @@ do_known_hosts(struct passwd *pw, const char *name, int find_host,
unlink(tmp);
fatal("fdopen: %s", strerror(oerrno));
}
+ fchmod(fd, sb.st_mode & 0644);
inplace = 1;
}
/* XXX support identity_file == "-" for stdin */
@@ -1334,10 +1341,10 @@ do_known_hosts(struct passwd *pw, const char *name, int find_host,
foreach_options |= print_fingerprint ? HKF_WANT_PARSE_KEY : 0;
if ((r = hostkeys_foreach(identity_file, (find_host || !hash_hosts) ?
known_hosts_find_delete : known_hosts_hash, &ctx, name, NULL,
- foreach_options)) != 0) {
+ foreach_options, 0)) != 0) {
if (inplace)
unlink(tmp);
- fatal("%s: hostkeys_foreach failed: %s", __func__, ssh_err(r));
+ fatal_fr(r, "hostkeys_foreach");
}
if (inplace)
@@ -1416,7 +1423,7 @@ do_change_passphrase(struct passwd *pw)
goto badkey;
} else if (r != 0) {
badkey:
- fatal("Failed to load key %s: %s", identity_file, ssh_err(r));
+ fatal_r(r, "Failed to load key %s", identity_file);
}
if (comment)
mprintf("Key has comment '%s'\n", comment);
@@ -1448,8 +1455,7 @@ do_change_passphrase(struct passwd *pw)
/* Save the file using the new passphrase. */
if ((r = sshkey_save_private(private, identity_file, passphrase1,
comment, private_key_format, openssh_format_cipher, rounds)) != 0) {
- error("Saving key \"%s\" failed: %s.",
- identity_file, ssh_err(r));
+ error_r(r, "Saving key \"%s\" failed", identity_file);
freezero(passphrase1, strlen(passphrase1));
sshkey_free(private);
free(comment);
@@ -1477,15 +1483,14 @@ do_print_resource_record(struct passwd *pw, char *fname, char *hname,
int r;
if (fname == NULL)
- fatal("%s: no filename", __func__);
+ fatal_f("no filename");
if (stat(fname, &st) == -1) {
if (errno == ENOENT)
return 0;
fatal("%s: %s", fname, strerror(errno));
}
if ((r = sshkey_load_public(fname, &public, &comment)) != 0)
- fatal("Failed to read v2 public key from \"%s\": %s.",
- fname, ssh_err(r));
+ fatal_r(r, "Failed to read v2 public key from \"%s\"", fname);
export_dns_rr(hname, public, stdout, print_generic);
sshkey_free(public);
free(comment);
@@ -1512,8 +1517,7 @@ do_change_comment(struct passwd *pw, const char *identity_comment)
&private, &comment)) == 0)
passphrase = xstrdup("");
else if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)
- fatal("Cannot load private key \"%s\": %s.",
- identity_file, ssh_err(r));
+ fatal_r(r, "Cannot load private key \"%s\"", identity_file);
else {
if (identity_passphrase)
passphrase = xstrdup(identity_passphrase);
@@ -1526,8 +1530,8 @@ do_change_comment(struct passwd *pw, const char *identity_comment)
if ((r = sshkey_load_private(identity_file, passphrase,
&private, &comment)) != 0) {
freezero(passphrase, strlen(passphrase));
- fatal("Cannot load private key \"%s\": %s.",
- identity_file, ssh_err(r));
+ fatal_r(r, "Cannot load private key \"%s\"",
+ identity_file);
}
}
@@ -1568,8 +1572,7 @@ do_change_comment(struct passwd *pw, const char *identity_comment)
if ((r = sshkey_save_private(private, identity_file, passphrase,
new_comment, private_key_format, openssh_format_cipher,
rounds)) != 0) {
- error("Saving key \"%s\" failed: %s",
- identity_file, ssh_err(r));
+ error_r(r, "Saving key \"%s\" failed", identity_file);
freezero(passphrase, strlen(passphrase));
sshkey_free(private);
free(comment);
@@ -1577,14 +1580,12 @@ do_change_comment(struct passwd *pw, const char *identity_comment)
}
freezero(passphrase, strlen(passphrase));
if ((r = sshkey_from_private(private, &public)) != 0)
- fatal("sshkey_from_private failed: %s", ssh_err(r));
+ fatal_fr(r, "sshkey_from_private");
sshkey_free(private);
strlcat(identity_file, ".pub", sizeof(identity_file));
- if ((r = sshkey_save_public(public, identity_file, new_comment)) != 0) {
- fatal("Unable to save public key to %s: %s",
- identity_file, ssh_err(r));
- }
+ if ((r = sshkey_save_public(public, identity_file, new_comment)) != 0)
+ fatal_r(r, "Unable to save public key to %s", identity_file);
sshkey_free(public);
free(comment);
@@ -1597,31 +1598,32 @@ do_change_comment(struct passwd *pw, const char *identity_comment)
}
static void
-add_flag_option(struct sshbuf *c, const char *name)
+cert_ext_add(const char *key, const char *value, int iscrit)
{
- int r;
-
- debug3("%s: %s", __func__, name);
- if ((r = sshbuf_put_cstring(c, name)) != 0 ||
- (r = sshbuf_put_string(c, NULL, 0)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ cert_ext = xreallocarray(cert_ext, ncert_ext + 1, sizeof(*cert_ext));
+ cert_ext[ncert_ext].key = xstrdup(key);
+ cert_ext[ncert_ext].val = value == NULL ? NULL : xstrdup(value);
+ cert_ext[ncert_ext].crit = iscrit;
+ ncert_ext++;
}
-static void
-add_string_option(struct sshbuf *c, const char *name, const char *value)
+/* qsort(3) comparison function for certificate extensions */
+static int
+cert_ext_cmp(const void *_a, const void *_b)
{
- struct sshbuf *b;
+ const struct cert_ext *a = (const struct cert_ext *)_a;
+ const struct cert_ext *b = (const struct cert_ext *)_b;
int r;
- debug3("%s: %s=%s", __func__, name, value);
- if ((b = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
- if ((r = sshbuf_put_cstring(b, value)) != 0 ||
- (r = sshbuf_put_cstring(c, name)) != 0 ||
- (r = sshbuf_put_stringb(c, b)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
-
- sshbuf_free(b);
+ if (a->crit != b->crit)
+ return (a->crit < b->crit) ? -1 : 1;
+ if ((r = strcmp(a->key, b->key)) != 0)
+ return r;
+ if ((a->val == NULL) != (b->val == NULL))
+ return (a->val == NULL) ? -1 : 1;
+ if (a->val != NULL && (r = strcmp(a->val, b->val)) != 0)
+ return r;
+ return 0;
}
#define OPTIONS_CRITICAL 1
@@ -1629,44 +1631,62 @@ add_string_option(struct sshbuf *c, const char *name, const char *value)
static void
prepare_options_buf(struct sshbuf *c, int which)
{
+ struct sshbuf *b;
size_t i;
+ int r;
+ const struct cert_ext *ext;
+ if ((b = sshbuf_new()) == NULL)
+ fatal_f("sshbuf_new failed");
sshbuf_reset(c);
- if ((which & OPTIONS_CRITICAL) != 0 &&
- certflags_command != NULL)
- add_string_option(c, "force-command", certflags_command);
- if ((which & OPTIONS_EXTENSIONS) != 0 &&
- (certflags_flags & CERTOPT_X_FWD) != 0)
- add_flag_option(c, "permit-X11-forwarding");
- if ((which & OPTIONS_EXTENSIONS) != 0 &&
- (certflags_flags & CERTOPT_AGENT_FWD) != 0)
- add_flag_option(c, "permit-agent-forwarding");
- if ((which & OPTIONS_EXTENSIONS) != 0 &&
- (certflags_flags & CERTOPT_PORT_FWD) != 0)
- add_flag_option(c, "permit-port-forwarding");
- if ((which & OPTIONS_EXTENSIONS) != 0 &&
- (certflags_flags & CERTOPT_PTY) != 0)
- add_flag_option(c, "permit-pty");
- if ((which & OPTIONS_EXTENSIONS) != 0 &&
- (certflags_flags & CERTOPT_USER_RC) != 0)
- add_flag_option(c, "permit-user-rc");
- if ((which & OPTIONS_EXTENSIONS) != 0 &&
- (certflags_flags & CERTOPT_NO_REQUIRE_USER_PRESENCE) != 0)
- add_flag_option(c, "no-touch-required");
- if ((which & OPTIONS_CRITICAL) != 0 &&
- certflags_src_addr != NULL)
- add_string_option(c, "source-address", certflags_src_addr);
- for (i = 0; i < ncert_userext; i++) {
- if ((cert_userext[i].crit && (which & OPTIONS_EXTENSIONS)) ||
- (!cert_userext[i].crit && (which & OPTIONS_CRITICAL)))
+ for (i = 0; i < ncert_ext; i++) {
+ ext = &cert_ext[i];
+ if ((ext->crit && (which & OPTIONS_EXTENSIONS)) ||
+ (!ext->crit && (which & OPTIONS_CRITICAL)))
continue;
- if (cert_userext[i].val == NULL)
- add_flag_option(c, cert_userext[i].key);
- else {
- add_string_option(c, cert_userext[i].key,
- cert_userext[i].val);
+ if (ext->val == NULL) {
+ /* flag option */
+ debug3_f("%s", ext->key);
+ if ((r = sshbuf_put_cstring(c, ext->key)) != 0 ||
+ (r = sshbuf_put_string(c, NULL, 0)) != 0)
+ fatal_fr(r, "prepare flag");
+ } else {
+ /* key/value option */
+ debug3_f("%s=%s", ext->key, ext->val);
+ sshbuf_reset(b);
+ if ((r = sshbuf_put_cstring(c, ext->key)) != 0 ||
+ (r = sshbuf_put_cstring(b, ext->val)) != 0 ||
+ (r = sshbuf_put_stringb(c, b)) != 0)
+ fatal_fr(r, "prepare k/v");
}
}
+ sshbuf_free(b);
+}
+
+static void
+finalise_cert_exts(void)
+{
+ /* critical options */
+ if (certflags_command != NULL)
+ cert_ext_add("force-command", certflags_command, 1);
+ if (certflags_src_addr != NULL)
+ cert_ext_add("source-address", certflags_src_addr, 1);
+ /* extensions */
+ if ((certflags_flags & CERTOPT_X_FWD) != 0)
+ cert_ext_add("permit-X11-forwarding", NULL, 0);
+ if ((certflags_flags & CERTOPT_AGENT_FWD) != 0)
+ cert_ext_add("permit-agent-forwarding", NULL, 0);
+ if ((certflags_flags & CERTOPT_PORT_FWD) != 0)
+ cert_ext_add("permit-port-forwarding", NULL, 0);
+ if ((certflags_flags & CERTOPT_PTY) != 0)
+ cert_ext_add("permit-pty", NULL, 0);
+ if ((certflags_flags & CERTOPT_USER_RC) != 0)
+ cert_ext_add("permit-user-rc", NULL, 0);
+ if ((certflags_flags & CERTOPT_NO_REQUIRE_USER_PRESENCE) != 0)
+ cert_ext_add("no-touch-required", NULL, 0);
+ /* order lexically by key */
+ if (ncert_ext > 0)
+ qsort(cert_ext, ncert_ext, sizeof(*cert_ext), cert_ext_cmp);
}
static struct sshkey *
@@ -1677,12 +1697,11 @@ load_pkcs11_key(char *path)
int r, i, nkeys;
if ((r = sshkey_load_public(path, &public, NULL)) != 0)
- fatal("Couldn't load CA public key \"%s\": %s",
- path, ssh_err(r));
+ fatal_r(r, "Couldn't load CA public key \"%s\"", path);
nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase,
&keys, NULL);
- debug3("%s: %d keys", __func__, nkeys);
+ debug3_f("%d keys", nkeys);
if (nkeys <= 0)
fatal("cannot read public key from pkcs11");
for (i = 0; i < nkeys; i++) {
@@ -1704,7 +1723,8 @@ load_pkcs11_key(char *path)
static int
agent_signer(struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen,
- const char *alg, const char *provider, u_int compat, void *ctx)
+ const char *alg, const char *provider, const char *pin,
+ u_int compat, void *ctx)
{
int *agent_fdp = (int *)ctx;
@@ -1721,7 +1741,7 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent,
u_int n;
struct sshkey *ca, *public;
char valid[64], *otmp, *tmp, *cp, *out, *comment;
- char *ca_fp = NULL, **plist = NULL;
+ char *ca_fp = NULL, **plist = NULL, *pin = NULL;
struct ssh_identitylist *agent_ids;
size_t j;
struct notifier_ctx *notifier = NULL;
@@ -1741,13 +1761,11 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent,
* agent.
*/
if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0)
- fatal("Cannot load CA public key %s: %s",
- tmp, ssh_err(r));
+ fatal_r(r, "Cannot load CA public key %s", tmp);
if ((r = ssh_get_authentication_socket(&agent_fd)) != 0)
- fatal("Cannot use public key for CA signature: %s",
- ssh_err(r));
+ fatal_r(r, "Cannot use public key for CA signature");
if ((r = ssh_fetch_identitylist(agent_fd, &agent_ids)) != 0)
- fatal("Retrieve agent key list: %s", ssh_err(r));
+ fatal_r(r, "Retrieve agent key list");
found = 0;
for (j = 0; j < agent_ids->nkeys; j++) {
if (sshkey_equal(ca, agent_ids->keys[j])) {
@@ -1762,6 +1780,12 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent,
} else {
/* CA key is assumed to be a private key on the filesystem */
ca = load_identity(tmp, NULL);
+ if (sshkey_is_sk(ca) &&
+ (ca->sk_flags & SSH_SK_USER_VERIFICATION_REQD)) {
+ if ((pin = read_passphrase("Enter PIN for CA key: ",
+ RP_ALLOW_STDIN)) == NULL)
+ fatal_f("couldn't read PIN");
+ }
}
free(tmp);
@@ -1776,6 +1800,7 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent,
}
ca_fp = sshkey_fingerprint(ca, fingerprint_hash, SSH_FP_DEFAULT);
+ finalise_cert_exts();
for (i = 0; i < argc; i++) {
/* Split list of principals */
n = 0;
@@ -1794,16 +1819,14 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent,
tmp = tilde_expand_filename(argv[i], pw->pw_uid);
if ((r = sshkey_load_public(tmp, &public, &comment)) != 0)
- fatal("%s: unable to open \"%s\": %s",
- __func__, tmp, ssh_err(r));
+ fatal_r(r, "load pubkey \"%s\"", tmp);
if (sshkey_is_cert(public))
- fatal("%s: key \"%s\" type %s cannot be certified",
- __func__, tmp, sshkey_type(public));
+ fatal_f("key \"%s\" type %s cannot be certified",
+ tmp, sshkey_type(public));
/* Prepare certificate to sign */
if ((r = sshkey_to_certified(public)) != 0)
- fatal("Could not upgrade key %s to certificate: %s",
- tmp, ssh_err(r));
+ fatal_r(r, "Could not upgrade key %s to certificate", tmp);
public->cert->type = cert_key_type;
public->cert->serial = (u_int64_t)cert_serial;
public->cert->key_id = xstrdup(cert_key_id);
@@ -1816,14 +1839,13 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent,
OPTIONS_EXTENSIONS);
if ((r = sshkey_from_private(ca,
&public->cert->signature_key)) != 0)
- fatal("sshkey_from_private (ca key): %s", ssh_err(r));
+ fatal_r(r, "sshkey_from_private (ca key)");
if (agent_fd != -1 && (ca->flags & SSHKEY_FLAG_EXT) != 0) {
if ((r = sshkey_certify_custom(public, ca,
- key_type_name, sk_provider, agent_signer,
+ key_type_name, sk_provider, NULL, agent_signer,
&agent_fd)) != 0)
- fatal("Couldn't certify key %s via agent: %s",
- tmp, ssh_err(r));
+ fatal_r(r, "Couldn't certify %s via agent", tmp);
} else {
if (sshkey_is_sk(ca) &&
(ca->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
@@ -1832,11 +1854,10 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent,
sshkey_type(ca), ca_fp);
}
r = sshkey_certify(public, ca, key_type_name,
- sk_provider);
- notify_complete(notifier);
+ sk_provider, pin);
+ notify_complete(notifier, "User presence confirmed");
if (r != 0)
- fatal("Couldn't certify key %s: %s",
- tmp, ssh_err(r));
+ fatal_r(r, "Couldn't certify key %s", tmp);
}
if ((cp = strrchr(tmp, '.')) != NULL && strcmp(cp, ".pub") == 0)
@@ -1845,8 +1866,8 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent,
free(tmp);
if ((r = sshkey_save_public(public, out, comment)) != 0) {
- fatal("Unable to save public key to %s: %s",
- identity_file, ssh_err(r));
+ fatal_r(r, "Unable to save public key to %s",
+ identity_file);
}
if (!quiet) {
@@ -1866,6 +1887,8 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent,
if (cert_serial_autoinc)
cert_serial++;
}
+ if (pin != NULL)
+ freezero(pin, strlen(pin));
free(ca_fp);
#ifdef ENABLE_PKCS11
pkcs11_terminate();
@@ -1986,17 +2009,12 @@ add_cert_option(char *opt)
fatal("Invalid source-address list");
certflags_src_addr = xstrdup(val);
} else if (strncasecmp(opt, "extension:", 10) == 0 ||
- (iscrit = (strncasecmp(opt, "critical:", 9) == 0))) {
+ (iscrit = (strncasecmp(opt, "critical:", 9) == 0))) {
val = xstrdup(strchr(opt, ':') + 1);
if ((cp = strchr(val, '=')) != NULL)
*cp++ = '\0';
- cert_userext = xreallocarray(cert_userext, ncert_userext + 1,
- sizeof(*cert_userext));
- cert_userext[ncert_userext].key = val;
- cert_userext[ncert_userext].val = cp == NULL ?
- NULL : xstrdup(cp);
- cert_userext[ncert_userext].crit = iscrit;
- ncert_userext++;
+ cert_ext_add(val, cp, iscrit);
+ free(val);
} else
fatal("Unsupported certificate option \"%s\"", opt);
}
@@ -2004,18 +2022,18 @@ add_cert_option(char *opt)
static void
show_options(struct sshbuf *optbuf, int in_critical)
{
- char *name, *arg;
+ char *name, *arg, *hex;
struct sshbuf *options, *option = NULL;
int r;
if ((options = sshbuf_fromb(optbuf)) == NULL)
- fatal("%s: sshbuf_fromb failed", __func__);
+ fatal_f("sshbuf_fromb failed");
while (sshbuf_len(options) != 0) {
sshbuf_free(option);
option = NULL;
if ((r = sshbuf_get_cstring(options, &name, NULL)) != 0 ||
(r = sshbuf_froms(options, &option)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse option");
printf(" %s", name);
if (!in_critical &&
(strcmp(name, "permit-X11-forwarding") == 0 ||
@@ -2029,15 +2047,17 @@ show_options(struct sshbuf *optbuf, int in_critical)
(strcmp(name, "force-command") == 0 ||
strcmp(name, "source-address") == 0)) {
if ((r = sshbuf_get_cstring(option, &arg, NULL)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "parse critical");
printf(" %s\n", arg);
free(arg);
- } else {
- printf(" UNKNOWN OPTION (len %zu)\n",
- sshbuf_len(option));
+ } else if (sshbuf_len(option) > 0) {
+ hex = sshbuf_dtob16(option);
+ printf(" UNKNOWN OPTION: %s (len %zu)\n",
+ hex, sshbuf_len(option));
sshbuf_reset(option);
- }
+ free(hex);
+ } else
+ printf(" UNKNOWN FLAG OPTION\n");
free(name);
if (sshbuf_len(option) != 0)
fatal("Option corrupt: extra data at end");
@@ -2056,7 +2076,7 @@ print_cert(struct sshkey *key)
ca_fp = sshkey_fingerprint(key->cert->signature_key,
fingerprint_hash, SSH_FP_DEFAULT);
if (key_fp == NULL || ca_fp == NULL)
- fatal("%s: sshkey_fingerprint fail", __func__);
+ fatal_f("sshkey_fingerprint fail");
sshkey_format_cert_validity(key->cert, valid, sizeof(valid));
printf(" Type: %s %s certificate\n", sshkey_ssh_name(key),
@@ -2129,8 +2149,7 @@ do_show_cert(struct passwd *pw)
if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
fatal("sshkey_new");
if ((r = sshkey_read(key, &cp)) != 0) {
- error("%s:%lu: invalid key: %s", path,
- lnum, ssh_err(r));
+ error_r(r, "%s:%lu: invalid key", path, lnum);
continue;
}
if (!sshkey_is_cert(key)) {
@@ -2157,11 +2176,11 @@ load_krl(const char *path, struct ssh_krl **krlp)
int r;
if ((r = sshbuf_load_file(path, &krlbuf)) != 0)
- fatal("Unable to load KRL: %s", ssh_err(r));
+ fatal_r(r, "Unable to load KRL %s", path);
/* XXX check sigs */
if ((r = ssh_krl_from_blob(krlbuf, krlp, NULL, 0)) != 0 ||
*krlp == NULL)
- fatal("Invalid KRL file: %s", ssh_err(r));
+ fatal_r(r, "Invalid KRL file %s", path);
sshbuf_free(krlbuf);
}
@@ -2190,9 +2209,9 @@ hash_to_blob(const char *cp, u_char **blobp, size_t *lenp,
tmp[tlen] = '\0';
}
if ((b = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_b64tod(b, tmp)) != 0)
- fatal("%s:%lu: decode hash failed: %s", file, lnum, ssh_err(r));
+ fatal_r(r, "%s:%lu: decode hash failed", file, lnum);
free(tmp);
*lenp = sshbuf_len(b);
*blobp = xmalloc(*lenp);
@@ -2278,8 +2297,7 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
}
if (ssh_krl_revoke_cert_by_serial_range(krl,
ca, serial, serial2) != 0) {
- fatal("%s: revoke serial failed",
- __func__);
+ fatal_f("revoke serial failed");
}
} else if (strncasecmp(cp, "id:", 3) == 0) {
if (ca == NULL && !wild_ca) {
@@ -2289,15 +2307,14 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
cp += 3;
cp = cp + strspn(cp, " \t");
if (ssh_krl_revoke_cert_by_key_id(krl, ca, cp) != 0)
- fatal("%s: revoke key ID failed", __func__);
+ fatal_f("revoke key ID failed");
} else if (strncasecmp(cp, "hash:", 5) == 0) {
cp += 5;
cp = cp + strspn(cp, " \t");
hash_to_blob(cp, &blob, &blen, file, lnum);
r = ssh_krl_revoke_key_sha256(krl, blob, blen);
if (r != 0)
- fatal("%s: revoke key failed: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "revoke key failed");
} else {
if (strncasecmp(cp, "key:", 4) == 0) {
cp += 4;
@@ -2319,8 +2336,7 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
fatal("sshkey_new");
if ((r = sshkey_read(key, &cp)) != 0)
- fatal("%s:%lu: invalid key: %s",
- path, lnum, ssh_err(r));
+ fatal_r(r, "%s:%lu: invalid key", path, lnum);
if (was_explicit_key)
r = ssh_krl_revoke_key_explicit(krl, key);
else if (was_sha1) {
@@ -2340,8 +2356,7 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
} else
r = ssh_krl_revoke_key(krl, key);
if (r != 0)
- fatal("%s: revoke key failed: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "revoke key failed");
freezero(blob, blen);
blob = NULL;
blen = 0;
@@ -2381,8 +2396,7 @@ do_gen_krl(struct passwd *pw, int updating, const char *ca_key_path,
else {
tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0)
- fatal("Cannot load CA public key %s: %s",
- tmp, ssh_err(r));
+ fatal_r(r, "Cannot load CA public key %s", tmp);
free(tmp);
}
}
@@ -2426,8 +2440,7 @@ do_check_krl(struct passwd *pw, int print_krl, int argc, char **argv)
krl_dump(krl, stdout);
for (i = 0; i < argc; i++) {
if ((r = sshkey_load_public(argv[i], &k, &comment)) != 0)
- fatal("Cannot load public key %s: %s",
- argv[i], ssh_err(r));
+ fatal_r(r, "Cannot load public key %s", argv[i]);
r = ssh_krl_check_key(krl, k);
printf("%s%s%s%s: %s\n", argv[i],
*comment ? " (" : "", comment, *comment ? ")" : "",
@@ -2461,8 +2474,8 @@ load_sign_key(const char *keypath, const struct sshkey *pubkey)
strcmp(privpath + plen - slen, suffixes[i]) != 0)
continue;
privpath[plen - slen] = '\0';
- debug("%s: %s looks like a public key, using private key "
- "path %s instead", __func__, keypath, privpath);
+ debug_f("%s looks like a public key, using private key "
+ "path %s instead", keypath, privpath);
}
if ((privkey = load_identity(privpath, NULL)) == NULL) {
error("Couldn't load identity %s", keypath);
@@ -2479,12 +2492,11 @@ load_sign_key(const char *keypath, const struct sshkey *pubkey)
* it capable of signing.
*/
if ((r = sshkey_to_certified(privkey)) != 0) {
- error("%s: sshkey_to_certified: %s", __func__,
- ssh_err(r));
+ error_fr(r, "sshkey_to_certified");
goto done;
}
if ((r = sshkey_cert_copy(pubkey, privkey)) != 0) {
- error("%s: sshkey_cert_copy: %s", __func__, ssh_err(r));
+ error_fr(r, "sshkey_cert_copy");
goto done;
}
}
@@ -2504,6 +2516,7 @@ sign_one(struct sshkey *signkey, const char *filename, int fd,
struct sshbuf *sigbuf = NULL, *abuf = NULL;
int r = SSH_ERR_INTERNAL_ERROR, wfd = -1, oerrno;
char *wfile = NULL, *asig = NULL, *fp = NULL;
+ char *pin = NULL, *prompt = NULL;
if (!quiet) {
if (fd == STDIN_FILENO)
@@ -2511,26 +2524,34 @@ sign_one(struct sshkey *signkey, const char *filename, int fd,
else
fprintf(stderr, "Signing file %s\n", filename);
}
- if (signer == NULL && sshkey_is_sk(signkey) &&
- (signkey->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
- if ((fp = sshkey_fingerprint(signkey, fingerprint_hash,
- SSH_FP_DEFAULT)) == NULL)
- fatal("%s: sshkey_fingerprint failed", __func__);
- fprintf(stderr, "Confirm user presence for key %s %s\n",
- sshkey_type(signkey), fp);
- free(fp);
+ if (signer == NULL && sshkey_is_sk(signkey)) {
+ if ((signkey->sk_flags & SSH_SK_USER_VERIFICATION_REQD)) {
+ xasprintf(&prompt, "Enter PIN for %s key: ",
+ sshkey_type(signkey));
+ if ((pin = read_passphrase(prompt,
+ RP_ALLOW_STDIN)) == NULL)
+ fatal_f("couldn't read PIN");
+ }
+ if ((signkey->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
+ if ((fp = sshkey_fingerprint(signkey, fingerprint_hash,
+ SSH_FP_DEFAULT)) == NULL)
+ fatal_f("fingerprint failed");
+ fprintf(stderr, "Confirm user presence for key %s %s\n",
+ sshkey_type(signkey), fp);
+ free(fp);
+ }
}
- if ((r = sshsig_sign_fd(signkey, NULL, sk_provider, fd, sig_namespace,
- &sigbuf, signer, signer_ctx)) != 0) {
- error("Signing %s failed: %s", filename, ssh_err(r));
+ if ((r = sshsig_sign_fd(signkey, NULL, sk_provider, pin,
+ fd, sig_namespace, &sigbuf, signer, signer_ctx)) != 0) {
+ error_r(r, "Signing %s failed", filename);
goto out;
}
if ((r = sshsig_armor(sigbuf, &abuf)) != 0) {
- error("%s: sshsig_armor: %s", __func__, ssh_err(r));
+ error_fr(r, "sshsig_armor");
goto out;
}
if ((asig = sshbuf_dup_string(abuf)) == NULL) {
- error("%s: buffer error", __func__);
+ error_f("buffer error");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
@@ -2569,7 +2590,10 @@ sign_one(struct sshkey *signkey, const char *filename, int fd,
r = 0;
out:
free(wfile);
+ free(prompt);
free(asig);
+ if (pin != NULL)
+ freezero(pin, strlen(pin));
sshbuf_free(abuf);
sshbuf_free(sigbuf);
if (wfd != -1)
@@ -2594,17 +2618,17 @@ sig_sign(const char *keypath, const char *sig_namespace, int argc, char **argv)
}
if ((r = sshkey_load_public(keypath, &pubkey, NULL)) != 0) {
- error("Couldn't load public key %s: %s", keypath, ssh_err(r));
+ error_r(r, "Couldn't load public key %s", keypath);
goto done;
}
if ((r = ssh_get_authentication_socket(&agent_fd)) != 0)
- debug("Couldn't get agent socket: %s", ssh_err(r));
+ debug_r(r, "Couldn't get agent socket");
else {
if ((r = ssh_agent_has_key(agent_fd, pubkey)) == 0)
signer = agent_signer;
else
- debug("Couldn't find key in agent: %s", ssh_err(r));
+ debug_r(r, "Couldn't find key in agent");
}
if (signer == NULL) {
@@ -2649,23 +2673,64 @@ done:
}
static int
+sig_process_opts(char * const *opts, size_t nopts, uint64_t *verify_timep,
+ int *print_pubkey)
+{
+ size_t i;
+ time_t now;
+
+ *verify_timep = 0;
+ if (print_pubkey != NULL)
+ *print_pubkey = 0;
+ for (i = 0; i < nopts; i++) {
+ if (strncasecmp(opts[i], "verify-time=", 12) == 0) {
+ if (parse_absolute_time(opts[i] + 12,
+ verify_timep) != 0 || *verify_timep == 0) {
+ error("Invalid \"verify-time\" option");
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
+ } else if (print_pubkey &&
+ strcasecmp(opts[i], "print-pubkey") == 0) {
+ *print_pubkey = 1;
+ } else {
+ error("Invalid option \"%s\"", opts[i]);
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
+ }
+ if (*verify_timep == 0) {
+ if ((now = time(NULL)) < 0) {
+ error("Time is before epoch");
+ return SSH_ERR_INVALID_ARGUMENT;
+ }
+ *verify_timep = (uint64_t)now;
+ }
+ return 0;
+}
+
+static int
sig_verify(const char *signature, const char *sig_namespace,
- const char *principal, const char *allowed_keys, const char *revoked_keys)
+ const char *principal, const char *allowed_keys, const char *revoked_keys,
+ char * const *opts, size_t nopts)
{
int r, ret = -1;
+ int print_pubkey = 0;
struct sshbuf *sigbuf = NULL, *abuf = NULL;
struct sshkey *sign_key = NULL;
char *fp = NULL;
struct sshkey_sig_details *sig_details = NULL;
+ uint64_t verify_time = 0;
+
+ if (sig_process_opts(opts, nopts, &verify_time, &print_pubkey) != 0)
+ goto done; /* error already logged */
memset(&sig_details, 0, sizeof(sig_details));
if ((r = sshbuf_load_file(signature, &abuf)) != 0) {
- error("Couldn't read signature file: %s", ssh_err(r));
+ error_r(r, "Couldn't read signature file");
goto done;
}
if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) {
- error("%s: sshsig_armor: %s", __func__, ssh_err(r));
+ error_fr(r, "sshsig_armor");
goto done;
}
if ((r = sshsig_verify_fd(sigbuf, STDIN_FILENO, sig_namespace,
@@ -2674,26 +2739,25 @@ sig_verify(const char *signature, const char *sig_namespace,
if ((fp = sshkey_fingerprint(sign_key, fingerprint_hash,
SSH_FP_DEFAULT)) == NULL)
- fatal("%s: sshkey_fingerprint failed", __func__);
+ fatal_f("sshkey_fingerprint failed");
debug("Valid (unverified) signature from key %s", fp);
if (sig_details != NULL) {
- debug2("%s: signature details: counter = %u, flags = 0x%02x",
- __func__, sig_details->sk_counter, sig_details->sk_flags);
+ debug2_f("signature details: counter = %u, flags = 0x%02x",
+ sig_details->sk_counter, sig_details->sk_flags);
}
free(fp);
fp = NULL;
if (revoked_keys != NULL) {
if ((r = sshkey_check_revoked(sign_key, revoked_keys)) != 0) {
- debug3("sshkey_check_revoked failed: %s", ssh_err(r));
+ debug3_fr(r, "sshkey_check_revoked");
goto done;
}
}
- if (allowed_keys != NULL &&
- (r = sshsig_check_allowed_keys(allowed_keys, sign_key,
- principal, sig_namespace)) != 0) {
- debug3("sshsig_check_allowed_keys failed: %s", ssh_err(r));
+ if (allowed_keys != NULL && (r = sshsig_check_allowed_keys(allowed_keys,
+ sign_key, principal, sig_namespace, verify_time)) != 0) {
+ debug3_fr(r, "sshsig_check_allowed_keys");
goto done;
}
/* success */
@@ -2702,23 +2766,30 @@ done:
if (!quiet) {
if (ret == 0) {
if ((fp = sshkey_fingerprint(sign_key, fingerprint_hash,
- SSH_FP_DEFAULT)) == NULL) {
- fatal("%s: sshkey_fingerprint failed",
- __func__);
- }
+ SSH_FP_DEFAULT)) == NULL)
+ fatal_f("sshkey_fingerprint failed");
if (principal == NULL) {
printf("Good \"%s\" signature with %s key %s\n",
- sig_namespace, sshkey_type(sign_key), fp);
+ sig_namespace, sshkey_type(sign_key), fp);
} else {
printf("Good \"%s\" signature for %s with %s key %s\n",
- sig_namespace, principal,
- sshkey_type(sign_key), fp);
+ sig_namespace, principal,
+ sshkey_type(sign_key), fp);
}
} else {
printf("Could not verify signature.\n");
}
}
+ /* Print the signature key if requested */
+ if (ret == 0 && print_pubkey && sign_key != NULL) {
+ if ((r = sshkey_write(sign_key, stdout)) == 0)
+ fputc('\n', stdout);
+ else {
+ error_r(r, "Could not print public key.\n");
+ ret = -1;
+ }
+ }
sshbuf_free(sigbuf);
sshbuf_free(abuf);
sshkey_free(sign_key);
@@ -2728,29 +2799,34 @@ done:
}
static int
-sig_find_principals(const char *signature, const char *allowed_keys) {
+sig_find_principals(const char *signature, const char *allowed_keys,
+ char * const *opts, size_t nopts)
+{
int r, ret = -1;
struct sshbuf *sigbuf = NULL, *abuf = NULL;
struct sshkey *sign_key = NULL;
char *principals = NULL, *cp, *tmp;
+ uint64_t verify_time = 0;
+
+ if (sig_process_opts(opts, nopts, &verify_time, NULL) != 0)
+ goto done; /* error already logged */
if ((r = sshbuf_load_file(signature, &abuf)) != 0) {
- error("Couldn't read signature file: %s", ssh_err(r));
+ error_r(r, "Couldn't read signature file");
goto done;
}
if ((r = sshsig_dearmor(abuf, &sigbuf)) != 0) {
- error("%s: sshsig_armor: %s", __func__, ssh_err(r));
+ error_fr(r, "sshsig_armor");
goto done;
}
if ((r = sshsig_get_pubkey(sigbuf, &sign_key)) != 0) {
- error("%s: sshsig_get_pubkey: %s",
- __func__, ssh_err(r));
+ error_fr(r, "sshsig_get_pubkey");
goto done;
}
if ((r = sshsig_find_principals(allowed_keys, sign_key,
- &principals)) != 0) {
- error("%s: sshsig_get_principal: %s",
- __func__, ssh_err(r));
+ verify_time, &principals)) != 0) {
+ if (r != SSH_ERR_KEY_NOT_FOUND)
+ error_fr(r, "sshsig_find_principal");
goto done;
}
ret = 0;
@@ -2934,27 +3010,24 @@ do_download_sk(const char *skprovider, const char *device)
{
struct sshkey **keys;
size_t nkeys, i;
- int r, ok = -1;
+ int r, ret = -1;
char *fp, *pin = NULL, *pass = NULL, *path, *pubpath;
const char *ext;
if (skprovider == NULL)
fatal("Cannot download keys without provider");
- for (i = 0; i < 2; i++) {
- if (i == 1) {
- pin = read_passphrase("Enter PIN for authenticator: ",
- RP_ALLOW_STDIN);
- }
- if ((r = sshsk_load_resident(skprovider, device, pin,
- &keys, &nkeys)) != 0) {
- if (i == 0 && r == SSH_ERR_KEY_WRONG_PASSPHRASE)
- continue;
- if (pin != NULL)
- freezero(pin, strlen(pin));
- error("Unable to load resident keys: %s", ssh_err(r));
- return -1;
- }
+ pin = read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN);
+ if (!quiet) {
+ printf("You may need to touch your authenticator "
+ "to authorize key download.\n");
+ }
+ if ((r = sshsk_load_resident(skprovider, device, pin,
+ &keys, &nkeys)) != 0) {
+ if (pin != NULL)
+ freezero(pin, strlen(pin));
+ error_r(r, "Unable to load resident keys");
+ return -1;
}
if (nkeys == 0)
logit("No keys to download");
@@ -2970,8 +3043,8 @@ do_download_sk(const char *skprovider, const char *device)
}
if ((fp = sshkey_fingerprint(keys[i],
fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
- fatal("%s: sshkey_fingerprint failed", __func__);
- debug("%s: key %zu: %s %s %s (flags 0x%02x)", __func__, i,
+ fatal_f("sshkey_fingerprint failed");
+ debug_f("key %zu: %s %s %s (flags 0x%02x)", i,
sshkey_type(keys[i]), fp, keys[i]->sk_application,
keys[i]->sk_flags);
ext = skip_ssh_url_preamble(keys[i]->sk_application);
@@ -2991,8 +3064,7 @@ do_download_sk(const char *skprovider, const char *device)
if ((r = sshkey_save_private(keys[i], path, pass,
keys[i]->sk_application, private_key_format,
openssh_format_cipher, rounds)) != 0) {
- error("Saving key \"%s\" failed: %s",
- path, ssh_err(r));
+ error_r(r, "Saving key \"%s\" failed", path);
free(path);
break;
}
@@ -3009,8 +3081,7 @@ do_download_sk(const char *skprovider, const char *device)
free(path);
if ((r = sshkey_save_public(keys[i], pubpath,
keys[i]->sk_application)) != 0) {
- error("Saving public key \"%s\" failed: %s",
- pubpath, ssh_err(r));
+ error_r(r, "Saving public key \"%s\" failed", pubpath);
free(pubpath);
break;
}
@@ -3018,28 +3089,51 @@ do_download_sk(const char *skprovider, const char *device)
}
if (i >= nkeys)
- ok = 0; /* success */
+ ret = 0; /* success */
if (pass != NULL)
freezero(pass, strlen(pass));
for (i = 0; i < nkeys; i++)
sshkey_free(keys[i]);
free(keys);
- return ok ? 0 : -1;
+ return ret;
+}
+
+static void
+save_attestation(struct sshbuf *attest, const char *path)
+{
+ mode_t omask;
+ int r;
+
+ if (path == NULL)
+ return; /* nothing to do */
+ if (attest == NULL || sshbuf_len(attest) == 0)
+ fatal("Enrollment did not return attestation data");
+ omask = umask(077);
+ r = sshbuf_write_file(path, attest);
+ umask(omask);
+ if (r != 0)
+ fatal_r(r, "Unable to write attestation data \"%s\"", path);
+ if (!quiet)
+ printf("Your FIDO attestation certificate has been saved in "
+ "%s\n", path);
}
static void
usage(void)
{
fprintf(stderr,
- "usage: ssh-keygen [-q] [-b bits] [-C comment] [-f output_keyfile] [-m format]\n"
+ "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"
- " [-N new_passphrase] [-O option] [-w provider]\n"
- " ssh-keygen -p [-f keyfile] [-m format] [-N new_passphrase]\n"
- " [-P old_passphrase]\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"
+#ifdef WITH_OPENSSL
" ssh-keygen -i [-f input_keyfile] [-m key_format]\n"
" ssh-keygen -e [-f input_keyfile] [-m key_format]\n"
+#endif
" ssh-keygen -y [-f input_keyfile]\n"
- " ssh-keygen -c [-C comment] [-f keyfile] [-P passphrase]\n"
+ " ssh-keygen -c [-a rounds] [-C comment] [-f keyfile] [-P passphrase]\n"
" ssh-keygen -l [-v] [-E fingerprint_hash] [-f input_keyfile]\n"
" ssh-keygen -B [-f input_keyfile]\n");
#ifdef ENABLE_PKCS11
@@ -3049,7 +3143,7 @@ usage(void)
fprintf(stderr,
" ssh-keygen -F hostname [-lv] [-f known_hosts_file]\n"
" ssh-keygen -H [-f known_hosts_file]\n"
- " ssh-keygen -K [-w provider]\n"
+ " ssh-keygen -K [-a rounds] [-w provider]\n"
" ssh-keygen -R hostname [-f known_hosts_file]\n"
" ssh-keygen -r hostname [-g] [-f input_keyfile]\n"
#ifdef WITH_OPENSSL
@@ -3060,7 +3154,7 @@ usage(void)
" [-n principals] [-O option] [-V validity_interval]\n"
" [-z serial_number] file ...\n"
" ssh-keygen -L [-f input_keyfile]\n"
- " ssh-keygen -A [-f prefix_path]\n"
+ " ssh-keygen -A [-a rounds] [-f prefix_path]\n"
" ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n"
" file ...\n"
" ssh-keygen -Q [-l] -f krl_file [file ...]\n"
@@ -3068,7 +3162,7 @@ usage(void)
" ssh-keygen -Y check-novalidate -n namespace -s signature_file\n"
" ssh-keygen -Y sign -f key_file -n namespace file ...\n"
" ssh-keygen -Y verify -f allowed_signers_file -I signer_identity\n"
- " -n namespace -s signature_file [-r revocation_file]\n");
+ " -n namespace -s signature_file [-r revocation_file]\n");
exit(1);
}
@@ -3078,11 +3172,10 @@ usage(void)
int
main(int argc, char **argv)
{
- char dotsshdir[PATH_MAX], comment[1024], *passphrase;
+ char comment[1024], *passphrase;
char *rr_hostname = NULL, *ep, *fp, *ra;
struct sshkey *private, *public;
struct passwd *pw;
- struct stat st;
int r, opt, type;
int change_passphrase = 0, change_comment = 0, show_cert = 0;
int find_host = 0, delete_host = 0, hash_hosts = 0;
@@ -3093,7 +3186,7 @@ main(int argc, char **argv)
unsigned long long cert_serial = 0;
char *identity_comment = NULL, *ca_key_path = NULL, **opts = NULL;
char *sk_application = NULL, *sk_device = NULL, *sk_user = NULL;
- char *sk_attestaion_path = NULL;
+ char *sk_attestation_path = NULL;
struct sshbuf *challenge = NULL, *attest = NULL;
size_t i, nopts = 0;
u_int32_t bits = 0;
@@ -3120,6 +3213,7 @@ main(int argc, char **argv)
pw = getpwuid(getuid());
if (!pw)
fatal("No user exists for uid %lu", (u_long)getuid());
+ pw = pwcopy(pw);
if (gethostname(hostname, sizeof(hostname)) == -1)
fatal("gethostname: %s", strerror(errno));
@@ -3225,6 +3319,9 @@ main(int argc, char **argv)
break;
case 'Z':
openssh_format_cipher = optarg;
+ if (cipher_by_name(openssh_format_cipher) == NULL)
+ fatal("Invalid OpenSSH-format cipher '%s'",
+ openssh_format_cipher);
break;
case 'C':
identity_comment = optarg;
@@ -3333,15 +3430,16 @@ main(int argc, char **argv)
if (strncmp(sign_op, "find-principals", 15) == 0) {
if (ca_key_path == NULL) {
error("Too few arguments for find-principals:"
- "missing signature file");
+ "missing signature file");
exit(1);
}
if (!have_identity) {
error("Too few arguments for find-principals:"
- "missing allowed keys file");
+ "missing allowed keys file");
exit(1);
}
- return sig_find_principals(ca_key_path, identity_file);
+ return sig_find_principals(ca_key_path, identity_file,
+ opts, nopts);
} else if (strncmp(sign_op, "sign", 4) == 0) {
if (cert_principals == NULL ||
*cert_principals == '\0') {
@@ -3359,11 +3457,11 @@ main(int argc, char **argv)
} else if (strncmp(sign_op, "check-novalidate", 16) == 0) {
if (ca_key_path == NULL) {
error("Too few arguments for check-novalidate: "
- "missing signature file");
+ "missing signature file");
exit(1);
}
return sig_verify(ca_key_path, cert_principals,
- NULL, NULL, NULL);
+ NULL, NULL, NULL, opts, nopts);
} else if (strncmp(sign_op, "verify", 6) == 0) {
if (cert_principals == NULL ||
*cert_principals == '\0') {
@@ -3387,7 +3485,8 @@ main(int argc, char **argv)
exit(1);
}
return sig_verify(ca_key_path, cert_principals,
- cert_key_id, identity_file, rr_hostname);
+ cert_key_id, identity_file, rr_hostname,
+ opts, nopts);
}
error("Unsupported operation for -Y: \"%s\"", sign_op);
usage();
@@ -3532,6 +3631,8 @@ main(int argc, char **argv)
for (i = 0; i < nopts; i++) {
if (strcasecmp(opts[i], "no-touch-required") == 0) {
sk_flags &= ~SSH_SK_USER_PRESENCE_REQD;
+ } else if (strcasecmp(opts[i], "verify-required") == 0) {
+ sk_flags |= SSH_SK_USER_VERIFICATION_REQD;
} else if (strcasecmp(opts[i], "resident") == 0) {
sk_flags |= SSH_SK_RESIDENT_KEY;
} else if (strncasecmp(opts[i], "device=", 7) == 0) {
@@ -3541,13 +3642,13 @@ main(int argc, char **argv)
} else if (strncasecmp(opts[i], "challenge=", 10) == 0) {
if ((r = sshbuf_load_file(opts[i] + 10,
&challenge)) != 0) {
- fatal("Unable to load FIDO enrollment "
- "challenge \"%s\": %s",
- opts[i] + 10, ssh_err(r));
+ fatal_r(r, "Unable to load FIDO "
+ "enrollment challenge \"%s\"",
+ opts[i] + 10);
}
} else if (strncasecmp(opts[i],
"write-attestation=", 18) == 0) {
- sk_attestaion_path = opts[i] + 18;
+ sk_attestation_path = opts[i] + 18;
} else if (strncasecmp(opts[i],
"application=", 12) == 0) {
sk_application = xstrdup(opts[i] + 12);
@@ -3564,9 +3665,15 @@ main(int argc, char **argv)
printf("You may need to touch your authenticator "
"to authorize key generation.\n");
}
- passphrase = NULL;
if ((attest = sshbuf_new()) == NULL)
fatal("sshbuf_new failed");
+ if ((sk_flags &
+ (SSH_SK_USER_VERIFICATION_REQD|SSH_SK_RESIDENT_KEY))) {
+ passphrase = read_passphrase("Enter PIN for "
+ "authenticator: ", RP_ALLOW_STDIN);
+ } else {
+ passphrase = NULL;
+ }
for (i = 0 ; ; i++) {
fflush(stdout);
r = sshsk_enroll(type, sk_provider, sk_device,
@@ -3576,10 +3683,9 @@ main(int argc, char **argv)
if (r == 0)
break;
if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)
- fatal("Key enrollment failed: %s", ssh_err(r));
- else if (i > 0)
+ fatal_r(r, "Key enrollment failed");
+ else if (passphrase != NULL) {
error("PIN incorrect");
- if (passphrase != NULL) {
freezero(passphrase, strlen(passphrase));
passphrase = NULL;
}
@@ -3587,6 +3693,11 @@ main(int argc, char **argv)
fatal("Too many incorrect PINs");
passphrase = read_passphrase("Enter PIN for "
"authenticator: ", RP_ALLOW_STDIN);
+ if (!quiet) {
+ printf("You may need to touch your "
+ "authenticator (again) to authorize "
+ "key generation.\n");
+ }
}
if (passphrase != NULL) {
freezero(passphrase, strlen(passphrase));
@@ -3599,26 +3710,14 @@ main(int argc, char **argv)
break;
}
if ((r = sshkey_from_private(private, &public)) != 0)
- fatal("sshkey_from_private failed: %s\n", ssh_err(r));
+ fatal_r(r, "sshkey_from_private");
if (!have_identity)
ask_filename(pw, "Enter file in which to save the key");
/* Create ~/.ssh directory if it doesn't already exist. */
- snprintf(dotsshdir, sizeof dotsshdir, "%s/%s",
- pw->pw_dir, _PATH_SSH_USER_DIR);
- if (strstr(identity_file, dotsshdir) != NULL) {
- if (stat(dotsshdir, &st) == -1) {
- if (errno != ENOENT) {
- error("Could not stat %s: %s", dotsshdir,
- strerror(errno));
- } else if (mkdir(dotsshdir, 0700) == -1) {
- error("Could not create directory '%s': %s",
- dotsshdir, strerror(errno));
- } else if (!quiet)
- printf("Created directory '%s'.\n", dotsshdir);
- }
- }
+ hostfile_create_user_ssh_dir(identity_file, !quiet);
+
/* If the file already exists, ask the user to confirm. */
if (!confirm_overwrite(identity_file))
exit(1);
@@ -3635,8 +3734,7 @@ main(int argc, char **argv)
/* Save the key with the given passphrase and comment. */
if ((r = sshkey_save_private(private, identity_file, passphrase,
comment, private_key_format, openssh_format_cipher, rounds)) != 0) {
- error("Saving key \"%s\" failed: %s",
- identity_file, ssh_err(r));
+ error_r(r, "Saving key \"%s\" failed", identity_file);
freezero(passphrase, strlen(passphrase));
exit(1);
}
@@ -3649,10 +3747,8 @@ main(int argc, char **argv)
}
strlcat(identity_file, ".pub", sizeof(identity_file));
- if ((r = sshkey_save_public(public, identity_file, comment)) != 0) {
- fatal("Unable to save public key to %s: %s",
- identity_file, ssh_err(r));
- }
+ if ((r = sshkey_save_public(public, identity_file, comment)) != 0)
+ fatal_r(r, "Unable to save public key to %s", identity_file);
if (!quiet) {
fp = sshkey_fingerprint(public, fingerprint_hash,
@@ -3671,20 +3767,9 @@ main(int argc, char **argv)
free(fp);
}
- if (sk_attestaion_path != NULL) {
- if (attest == NULL || sshbuf_len(attest) == 0) {
- fatal("Enrollment did not return attestation "
- "certificate");
- }
- if ((r = sshbuf_write_file(sk_attestaion_path, attest)) != 0) {
- fatal("Unable to write attestation certificate "
- "\"%s\": %s", sk_attestaion_path, ssh_err(r));
- }
- if (!quiet) {
- printf("Your FIDO attestation certificate has been "
- "saved in %s\n", sk_attestaion_path);
- }
- }
+ if (sk_attestation_path != NULL)
+ save_attestation(attest, sk_attestation_path);
+
sshbuf_free(attest);
sshkey_free(public);
diff --git a/ssh-keyscan.c b/ssh-keyscan.c
index a5e644076..7abbcbff5 100644
--- a/ssh-keyscan.c
+++ b/ssh-keyscan.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keyscan.c,v 1.131 2019/12/15 19:47:10 djm Exp $ */
+/* $OpenBSD: ssh-keyscan.c,v 1.139 2021/01/27 09:26:54 djm Exp $ */
/*
* Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
*
@@ -293,7 +293,7 @@ keygrab_ssh2(con *c)
# endif
#endif
c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client;
- c->c_ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client;
+ c->c_ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client;
ssh_set_verify_host_key_callback(c->c_ssh, key_print_wrapper);
/*
* do the key-exchange until an error occurs or until
@@ -367,7 +367,7 @@ tcpconnect(char *host)
continue;
}
if (set_nonblock(s) == -1)
- fatal("%s: set_nonblock(%d)", __func__, s);
+ fatal_f("set_nonblock(%d)", s);
if (connect(s, ai->ai_addr, ai->ai_addrlen) == -1 &&
errno != EINPROGRESS)
error("connect (`%s'): %s", host, strerror(errno));
@@ -401,7 +401,7 @@ conalloc(char *iname, char *oname, int keytype)
if (fdcon[s].c_status)
fatal("conalloc: attempt to reuse fdno %d", s);
- debug3("%s: oname %s kt %d", __func__, oname, keytype);
+ debug3_f("oname %s kt %d", oname, keytype);
fdcon[s].c_fd = s;
fdcon[s].c_status = CS_CON;
fdcon[s].c_namebase = namebase;
@@ -522,11 +522,10 @@ congreet(int s)
fatal("ssh_packet_set_connection failed");
ssh_packet_set_timeout(c->c_ssh, timeout, 1);
ssh_set_app_data(c->c_ssh, c); /* back link */
+ c->c_ssh->compat = 0;
if (sscanf(buf, "SSH-%d.%d-%[^\n]\n",
&remote_major, &remote_minor, remote_version) == 3)
- c->c_ssh->compat = compat_datafellows(remote_version);
- else
- c->c_ssh->compat = 0;
+ compat_banner(c->c_ssh, remote_version);
if (!ssh2_capable(remote_major, remote_minor)) {
debug("%s doesn't support ssh2", c->c_name);
confree(s);
@@ -584,16 +583,9 @@ conloop(void)
monotime_tv(&now);
c = TAILQ_FIRST(&tq);
- if (c && (c->c_tv.tv_sec > now.tv_sec ||
- (c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec > now.tv_usec))) {
- seltime = c->c_tv;
- seltime.tv_sec -= now.tv_sec;
- seltime.tv_usec -= now.tv_usec;
- if (seltime.tv_usec < 0) {
- seltime.tv_usec += 1000000;
- seltime.tv_sec--;
- }
- } else
+ if (c && timercmp(&c->c_tv, &now, >))
+ timersub(&c->c_tv, &now, &seltime);
+ else
timerclear(&seltime);
r = xcalloc(read_wait_nfdset, sizeof(fd_mask));
@@ -616,8 +608,7 @@ conloop(void)
free(e);
c = TAILQ_FIRST(&tq);
- while (c && (c->c_tv.tv_sec < now.tv_sec ||
- (c->c_tv.tv_sec == now.tv_sec && c->c_tv.tv_usec < now.tv_usec))) {
+ while (c && timercmp(&c->c_tv, &now, <)) {
int s = c->c_fd;
c = TAILQ_NEXT(c, c_link);
@@ -643,14 +634,15 @@ do_host(char *host)
}
void
-fatal(const char *fmt,...)
+sshfatal(const char *file, const char *func, int line, int showfunc,
+ LogLevel level, const char *suffix, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
- do_log(SYSLOG_LEVEL_FATAL, fmt, args);
+ sshlogv(file, func, line, showfunc, level, suffix, fmt, args);
va_end(args);
- exit(255);
+ cleanup_exit(255);
}
static void
@@ -794,8 +786,7 @@ main(int argc, char **argv)
if (argv[j] == NULL)
fp = stdin;
else if ((fp = fopen(argv[j], "r")) == NULL)
- fatal("%s: %s: %s", __progname, argv[j],
- strerror(errno));
+ fatal("%s: %s: %s", __progname, argv[j], strerror(errno));
while (getline(&line, &linesize, fp) != -1) {
/* Chomp off trailing whitespace and comments */
@@ -817,8 +808,7 @@ main(int argc, char **argv)
}
if (ferror(fp))
- fatal("%s: %s: %s", __progname, argv[j],
- strerror(errno));
+ fatal("%s: %s: %s", __progname, argv[j], strerror(errno));
fclose(fp);
}
diff --git a/ssh-keysign.c b/ssh-keysign.c
index 3e3ea3e14..d6ac98c6c 100644
--- a/ssh-keysign.c
+++ b/ssh-keysign.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keysign.c,v 1.63 2019/11/18 16:10:05 naddy Exp $ */
+/* $OpenBSD: ssh-keysign.c,v 1.67 2021/07/05 01:16:46 dtucker Exp $ */
/*
* Copyright (c) 2002 Markus Friedl. All rights reserved.
*
@@ -78,33 +78,33 @@ valid_request(struct passwd *pw, char *host, struct sshkey **ret,
fail = 0;
if ((b = sshbuf_from(data, datalen)) == NULL)
- fatal("%s: sshbuf_from failed", __func__);
+ fatal_f("sshbuf_from failed");
/* session id, currently limited to SHA1 (20 bytes) or SHA256 (32) */
if ((r = sshbuf_get_string(b, NULL, &len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse session ID");
if (len != 20 && len != 32)
fail++;
if ((r = sshbuf_get_u8(b, &type)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse type");
if (type != SSH2_MSG_USERAUTH_REQUEST)
fail++;
/* server user */
if ((r = sshbuf_skip_string(b)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse user");
/* service */
if ((r = sshbuf_get_cstring(b, &p, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse service");
if (strcmp("ssh-connection", p) != 0)
fail++;
free(p);
/* method */
if ((r = sshbuf_get_cstring(b, &p, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse method");
if (strcmp("hostbased", p) != 0)
fail++;
free(p);
@@ -112,13 +112,13 @@ valid_request(struct passwd *pw, char *host, struct sshkey **ret,
/* pubkey */
if ((r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0 ||
(r = sshbuf_get_string(b, &pkblob, &blen)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse pk");
pktype = sshkey_type_from_name(pkalg);
if (pktype == KEY_UNSPEC)
fail++;
else if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
- error("%s: bad key blob: %s", __func__, ssh_err(r));
+ error_fr(r, "decode key");
fail++;
} else if (key->type != pktype)
fail++;
@@ -127,8 +127,8 @@ valid_request(struct passwd *pw, char *host, struct sshkey **ret,
/* client host name, handle trailing dot */
if ((r = sshbuf_get_cstring(b, &p, &len)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- debug2("%s: check expect chost %s got %s", __func__, host, p);
+ fatal_fr(r, "parse hostname");
+ debug2_f("check expect chost %s got %s", host, p);
if (strlen(host) != len - 1)
fail++;
else if (p[len - 1] != '.')
@@ -139,7 +139,7 @@ valid_request(struct passwd *pw, char *host, struct sshkey **ret,
/* local user */
if ((r = sshbuf_get_cstring(b, &luser, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse luser");
if (strcmp(pw->pw_name, luser) != 0)
fail++;
@@ -150,7 +150,7 @@ valid_request(struct passwd *pw, char *host, struct sshkey **ret,
fail++;
sshbuf_free(b);
- debug3("%s: fail %d", __func__, fail);
+ debug3_f("fail %d", fail);
if (fail)
sshkey_free(key);
@@ -207,7 +207,7 @@ main(int argc, char **argv)
initialize_options(&options);
(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, "", "",
&options, 0, NULL);
- fill_default_options(&options);
+ (void)fill_default_options(&options);
if (options.enable_ssh_keysign != 1)
fatal("ssh-keysign not enabled in %s",
_PATH_HOST_CONFIG_FILE);
@@ -228,7 +228,7 @@ main(int argc, char **argv)
NULL, &key, NULL);
close(key_fd[i]);
if (r != 0)
- debug("parse key %d: %s", i, ssh_err(r));
+ debug_r(r, "parse key %d", i);
else if (key != NULL) {
keys[i] = key;
found = 1;
@@ -243,22 +243,23 @@ main(int argc, char **argv)
if ((b = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __progname);
if (ssh_msg_recv(STDIN_FILENO, b) < 0)
- fatal("ssh_msg_recv failed");
+ fatal("%s: ssh_msg_recv failed", __progname);
if ((r = sshbuf_get_u8(b, &rver)) != 0)
- fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ fatal_r(r, "%s: buffer error", __progname);
if (rver != version)
- fatal("bad version: received %d, expected %d", rver, version);
+ fatal("%s: bad version: received %d, expected %d",
+ __progname, rver, version);
if ((r = sshbuf_get_u32(b, (u_int *)&fd)) != 0)
- fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ fatal_r(r, "%s: buffer error", __progname);
if (fd < 0 || fd == STDIN_FILENO || fd == STDOUT_FILENO)
- fatal("bad fd = %d", fd);
+ fatal("%s: bad fd = %d", __progname, fd);
if ((host = get_local_name(fd)) == NULL)
- fatal("cannot get local name for fd");
+ fatal("%s: cannot get local name for fd", __progname);
if ((r = sshbuf_get_string(b, &data, &dlen)) != 0)
- fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ fatal_r(r, "%s: buffer error", __progname);
if (valid_request(pw, host, &key, data, dlen) < 0)
- fatal("not a valid request");
+ fatal("%s: not a valid request", __progname);
free(host);
found = 0;
@@ -273,21 +274,21 @@ main(int argc, char **argv)
if ((fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL)
fatal("%s: sshkey_fingerprint failed", __progname);
- fatal("no matching hostkey found for key %s %s",
+ fatal("%s: no matching hostkey found for key %s %s", __progname,
sshkey_type(key), fp ? fp : "");
}
if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen,
- NULL, NULL, 0)) != 0)
- fatal("sshkey_sign failed: %s", ssh_err(r));
+ NULL, NULL, NULL, 0)) != 0)
+ fatal_r(r, "%s: sshkey_sign failed", __progname);
free(data);
/* send reply */
sshbuf_reset(b);
if ((r = sshbuf_put_string(b, signature, slen)) != 0)
- fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ fatal_r(r, "%s: buffer error", __progname);
if (ssh_msg_send(STDOUT_FILENO, version, b) == -1)
- fatal("ssh_msg_send failed");
+ fatal("%s: ssh_msg_send failed", __progname);
return (0);
}
diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c
index 8a0ffef5d..e72473694 100644
--- a/ssh-pkcs11-client.c
+++ b/ssh-pkcs11-client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-pkcs11-client.c,v 1.16 2020/01/25 00:03:36 djm Exp $ */
+/* $OpenBSD: ssh-pkcs11-client.c,v 1.17 2020/10/18 11:32:02 djm Exp $ */
/*
* Copyright (c) 2010 Markus Friedl. All rights reserved.
* Copyright (c) 2014 Pedro Martelletto. All rights reserved.
@@ -65,7 +65,7 @@ send_msg(struct sshbuf *m)
sshbuf_len(m)) != sshbuf_len(m))
error("write to helper failed");
if ((r = sshbuf_consume(m, mlen)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "consume");
}
static int
@@ -93,11 +93,11 @@ recv_msg(struct sshbuf *m)
return (0); /* XXX */
}
if ((r = sshbuf_put(m, buf, l)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_put");
len -= l;
}
if ((r = sshbuf_get_u8(m, &c)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse type");
return c;
}
@@ -127,29 +127,29 @@ rsa_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
goto fail;
key = sshkey_new(KEY_UNSPEC);
if (key == NULL) {
- error("%s: sshkey_new failed", __func__);
+ error_f("sshkey_new failed");
goto fail;
}
key->type = KEY_RSA;
RSA_up_ref(rsa);
key->rsa = rsa;
if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) {
- error("%s: sshkey_to_blob: %s", __func__, ssh_err(r));
+ error_fr(r, "encode key");
goto fail;
}
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 ||
(r = sshbuf_put_string(msg, blob, blen)) != 0 ||
(r = sshbuf_put_string(msg, from, flen)) != 0 ||
(r = sshbuf_put_u32(msg, 0)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
send_msg(msg);
sshbuf_reset(msg);
if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) {
if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (slen <= (size_t)RSA_size(rsa)) {
memcpy(to, signature, slen);
ret = slen;
@@ -178,13 +178,13 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
nid = sshkey_ecdsa_key_to_nid(ec);
if (nid < 0) {
- error("%s: couldn't get curve nid", __func__);
+ error_f("couldn't get curve nid");
goto fail;
}
key = sshkey_new(KEY_UNSPEC);
if (key == NULL) {
- error("%s: sshkey_new failed", __func__);
+ error_f("sshkey_new failed");
goto fail;
}
key->ecdsa = ec;
@@ -193,22 +193,22 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
EC_KEY_up_ref(ec);
if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) {
- error("%s: sshkey_to_blob: %s", __func__, ssh_err(r));
+ error_fr(r, "encode key");
goto fail;
}
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 ||
(r = sshbuf_put_string(msg, blob, blen)) != 0 ||
(r = sshbuf_put_string(msg, dgst, dgst_len)) != 0 ||
(r = sshbuf_put_u32(msg, 0)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
send_msg(msg);
sshbuf_reset(msg);
if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) {
if ((r = sshbuf_get_string(msg, &signature, &slen)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
cp = signature;
ret = d2i_ECDSA_SIG(NULL, &cp, slen);
free(signature);
@@ -238,7 +238,7 @@ wrap_key(struct sshkey *k)
EC_KEY_set_method(k->ecdsa, helper_ecdsa);
#endif /* HAVE_EC_KEY_METHOD_NEW */
else
- fatal("%s: unknown key type", __func__);
+ fatal_f("unknown key type");
}
static int
@@ -260,10 +260,10 @@ pkcs11_start_helper_methods(void)
#endif /* HAVE_EC_KEY_METHOD_NEW */
if ((helper_rsa = RSA_meth_dup(RSA_get_default_method())) == NULL)
- fatal("%s: RSA_meth_dup failed", __func__);
+ fatal_f("RSA_meth_dup failed");
if (!RSA_meth_set1_name(helper_rsa, "ssh-pkcs11-helper") ||
!RSA_meth_set_priv_enc(helper_rsa, rsa_encrypt))
- fatal("%s: failed to prepare method", __func__);
+ fatal_f("failed to prepare method");
return (0);
}
@@ -300,7 +300,7 @@ pkcs11_start_helper(void)
helper = getenv("SSH_PKCS11_HELPER");
if (helper == NULL || strlen(helper) == 0)
helper = _PATH_SSH_PKCS11_HELPER;
- debug("%s: starting %s %s", __func__, helper,
+ debug_f("starting %s %s", helper,
verbosity == NULL ? "" : verbosity);
execlp(helper, helper, verbosity, (char *)NULL);
fprintf(stderr, "exec: %s: %s\n", helper, strerror(errno));
@@ -327,18 +327,18 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
return (-1);
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, SSH_AGENTC_ADD_SMARTCARD_KEY)) != 0 ||
(r = sshbuf_put_cstring(msg, name)) != 0 ||
(r = sshbuf_put_cstring(msg, pin)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
send_msg(msg);
sshbuf_reset(msg);
type = recv_msg(msg);
if (type == SSH2_AGENT_IDENTITIES_ANSWER) {
if ((r = sshbuf_get_u32(msg, &nkeys)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse nkeys");
*keysp = xcalloc(nkeys, sizeof(struct sshkey *));
if (labelsp)
*labelsp = xcalloc(nkeys, sizeof(char *));
@@ -346,10 +346,9 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp,
/* XXX clean up properly instead of fatal() */
if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 ||
(r = sshbuf_get_cstring(msg, &label, NULL)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "parse key");
if ((r = sshkey_from_blob(blob, blen, &k)) != 0)
- fatal("%s: bad key: %s", __func__, ssh_err(r));
+ fatal_fr(r, "decode key");
wrap_key(k);
(*keysp)[i] = k;
if (labelsp)
@@ -375,11 +374,11 @@ pkcs11_del_provider(char *name)
struct sshbuf *msg;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_u8(msg, SSH_AGENTC_REMOVE_SMARTCARD_KEY)) != 0 ||
(r = sshbuf_put_cstring(msg, name)) != 0 ||
(r = sshbuf_put_cstring(msg, "")) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
send_msg(msg);
sshbuf_reset(msg);
diff --git a/ssh-pkcs11-helper.c b/ssh-pkcs11-helper.c
index d73e83576..5ca8d03fb 100644
--- a/ssh-pkcs11-helper.c
+++ b/ssh-pkcs11-helper.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-pkcs11-helper.c,v 1.23 2020/03/06 18:26:21 markus Exp $ */
+/* $OpenBSD: ssh-pkcs11-helper.c,v 1.25 2021/08/11 05:20:17 djm Exp $ */
/*
* Copyright (c) 2010 Markus Friedl. All rights reserved.
*
@@ -98,7 +98,8 @@ lookup_key(struct sshkey *k)
struct pkcs11_keyinfo *ki;
TAILQ_FOREACH(ki, &pkcs11_keylist, next) {
- debug("check %p %s %s", ki, ki->providername, ki->label);
+ debug("check %s %s %s", sshkey_type(ki->key),
+ ki->providername, ki->label);
if (sshkey_equal(k, ki->key))
return (ki->key);
}
@@ -111,7 +112,7 @@ send_msg(struct sshbuf *m)
int r;
if ((r = sshbuf_put_stringb(oqueue, m)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "enqueue");
}
static void
@@ -126,35 +127,30 @@ process_add(void)
char **labels = NULL;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
(r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if ((nkeys = pkcs11_add_provider(name, pin, &keys, &labels)) > 0) {
if ((r = sshbuf_put_u8(msg,
SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
(r = sshbuf_put_u32(msg, nkeys)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
for (i = 0; i < nkeys; i++) {
if ((r = sshkey_to_blob(keys[i], &blob, &blen)) != 0) {
- debug("%s: sshkey_to_blob: %s",
- __func__, ssh_err(r));
+ debug_fr(r, "encode key");
continue;
}
if ((r = sshbuf_put_string(msg, blob, blen)) != 0 ||
(r = sshbuf_put_cstring(msg, labels[i])) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "compose key");
free(blob);
add_key(keys[i], name, labels[i]);
free(labels[i]);
}
- } else {
- if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- if ((r = sshbuf_put_u32(msg, -nkeys)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
- }
+ } else if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0 ||
+ (r = sshbuf_put_u32(msg, -nkeys)) != 0)
+ fatal_fr(r, "compose");
free(labels);
free(keys); /* keys themselves are transferred to pkcs11_keylist */
free(pin);
@@ -171,14 +167,14 @@ process_del(void)
int r;
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
(r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
del_keys_by_name(name);
if ((r = sshbuf_put_u8(msg, pkcs11_del_provider(name) == 0 ?
SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
free(pin);
free(name);
send_msg(msg);
@@ -198,10 +194,10 @@ process_sign(void)
if ((r = sshbuf_get_string(iqueue, &blob, &blen)) != 0 ||
(r = sshbuf_get_string(iqueue, &data, &dlen)) != 0 ||
(r = sshbuf_get_u32(iqueue, NULL)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if ((r = sshkey_from_blob(blob, blen, &key)) != 0)
- error("%s: sshkey_from_blob: %s", __func__, ssh_err(r));
+ fatal_fr(r, "decode key");
else {
if ((found = lookup_key(key)) != NULL) {
#ifdef WITH_OPENSSL
@@ -227,26 +223,25 @@ process_sign(void)
if (ret != 0)
ok = 0;
else
- error("%s: ECDSA_sign"
- " returns %d", __func__, ret);
+ error_f("ECDSA_sign returned %d", ret);
slen = xslen;
#endif /* OPENSSL_HAS_ECC */
} else
- error("%s: don't know how to sign with key "
- "type %d", __func__, (int)key->type);
+ error_f("don't know how to sign with key "
+ "type %d", (int)key->type);
#endif /* WITH_OPENSSL */
}
sshkey_free(key);
}
if ((msg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if (ok == 0) {
if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 ||
(r = sshbuf_put_string(msg, signature, slen)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose response");
} else {
if ((r = sshbuf_put_u8(msg, SSH2_AGENT_FAILURE)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose failure response");
}
free(data);
free(blob);
@@ -278,7 +273,7 @@ process(void)
return;
if ((r = sshbuf_consume(iqueue, 4)) != 0 ||
(r = sshbuf_get_u8(iqueue, &type)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse type/len");
buf_len -= 4;
switch (type) {
case SSH_AGENTC_ADD_SMARTCARD_KEY:
@@ -309,7 +304,7 @@ process(void)
}
if (msg_len > consumed) {
if ((r = sshbuf_consume(iqueue, msg_len - consumed)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "consume");
}
}
@@ -356,14 +351,13 @@ main(int argc, char **argv)
log_init(__progname, log_level, log_facility, log_stderr);
pkcs11_init(0);
-
in = STDIN_FILENO;
out = STDOUT_FILENO;
if ((iqueue = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((oqueue = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
while (1) {
memset(pfd, 0, sizeof(pfd));
@@ -379,7 +373,7 @@ main(int argc, char **argv)
(r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0)
pfd[0].events = POLLIN;
else if (r != SSH_ERR_NO_BUFFER_SPACE)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reserve");
if (sshbuf_len(oqueue) > 0)
pfd[1].events = POLLOUT;
@@ -399,10 +393,8 @@ main(int argc, char **argv)
} else if (len < 0) {
error("read: %s", strerror(errno));
cleanup_exit(1);
- } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) {
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
- }
+ } else if ((r = sshbuf_put(iqueue, buf, len)) != 0)
+ fatal_fr(r, "sshbuf_put");
}
/* send oqueue to stdout */
if ((pfd[1].revents & (POLLOUT|POLLHUP)) != 0) {
@@ -411,10 +403,8 @@ main(int argc, char **argv)
if (len < 0) {
error("write: %s", strerror(errno));
cleanup_exit(1);
- } else if ((r = sshbuf_consume(oqueue, len)) != 0) {
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
- }
+ } else if ((r = sshbuf_consume(oqueue, len)) != 0)
+ fatal_fr(r, "consume");
}
/*
@@ -425,7 +415,7 @@ main(int argc, char **argv)
if ((r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0)
process();
else if (r != SSH_ERR_NO_BUFFER_SPACE)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "reserve");
}
}
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
index ec0e91865..37a6b1b5b 100644
--- a/ssh-pkcs11.c
+++ b/ssh-pkcs11.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-pkcs11.c,v 1.49 2020/03/13 04:16:27 djm Exp $ */
+/* $OpenBSD: ssh-pkcs11.c,v 1.54 2021/08/11 05:20:17 djm Exp $ */
/*
* Copyright (c) 2010 Markus Friedl. All rights reserved.
* Copyright (c) 2014 Pedro Martelletto. All rights reserved.
@@ -46,6 +46,7 @@
#include "misc.h"
#include "sshkey.h"
#include "ssh-pkcs11.h"
+#include "digest.h"
#include "xmalloc.h"
struct pkcs11_slotinfo {
@@ -84,10 +85,9 @@ ossl_error(const char *msg)
{
unsigned long e;
- error("%s: %s", __func__, msg);
+ error_f("%s", msg);
while ((e = ERR_get_error()) != 0)
- error("%s: libcrypto error: %.100s", __func__,
- ERR_error_string(e, NULL));
+ error_f("libcrypto error: %s", ERR_error_string(e, NULL));
}
#endif /* HAVE_EC_KEY_METHOD_NEW */
@@ -111,8 +111,8 @@ pkcs11_provider_finalize(struct pkcs11_provider *p)
CK_RV rv;
CK_ULONG i;
- debug("pkcs11_provider_finalize: %p refcount %d valid %d",
- p, p->refcount, p->valid);
+ debug_f("provider \"%s\" refcount %d valid %d",
+ p->name, p->refcount, p->valid);
if (!p->valid)
return;
for (i = 0; i < p->nslots; i++) {
@@ -135,10 +135,10 @@ pkcs11_provider_finalize(struct pkcs11_provider *p)
static void
pkcs11_provider_unref(struct pkcs11_provider *p)
{
- debug("pkcs11_provider_unref: %p refcount %d", p, p->refcount);
+ debug_f("provider \"%s\" refcount %d", p->name, p->refcount);
if (--p->refcount <= 0) {
if (p->valid)
- error("pkcs11_provider_unref: %p still valid", p);
+ error_f("provider \"%s\" still valid", p->name);
free(p->name);
free(p->slotlist);
free(p->slotinfo);
@@ -166,7 +166,7 @@ pkcs11_provider_lookup(char *provider_id)
struct pkcs11_provider *p;
TAILQ_FOREACH(p, &pkcs11_providers, next) {
- debug("check %p %s", p, p->name);
+ debug("check provider \"%s\"", p->name);
if (!strcmp(provider_id, p->name))
return (p);
}
@@ -202,7 +202,7 @@ pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx,
{
struct pkcs11_key *k11 = ptr;
- debug("%s: parent %p ptr %p idx %d", __func__, parent, ptr, idx);
+ debug_f("parent %p ptr %p idx %d", parent, ptr, idx);
if (k11 == NULL)
return;
if (k11->provider)
@@ -263,7 +263,7 @@ pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si,
snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ",
si->token.label);
if ((pin = read_passphrase(prompt, RP_ALLOW_EOF)) == NULL) {
- debug("%s: no pin specified", __func__);
+ debug_f("no pin specified");
return (-1); /* bail out */
}
}
@@ -337,8 +337,8 @@ pkcs11_check_obj_bool_attrib(struct pkcs11_key *k11, CK_OBJECT_HANDLE obj,
return (-1);
}
*val = flag != 0;
- debug("%s: provider %p slot %lu object %lu: attrib %lu = %d",
- __func__, k11->provider, k11->slotidx, obj, type, *val);
+ debug_f("provider \"%s\" slot %lu object %lu: attrib %lu = %d",
+ k11->provider->name, k11->slotidx, obj, type, *val);
return (0);
}
@@ -407,7 +407,7 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type)
pkcs11_check_obj_bool_attrib(k11, obj, CKA_ALWAYS_AUTHENTICATE,
&always_auth); /* ignore errors here */
if (always_auth && !did_login) {
- debug("%s: always-auth key", __func__);
+ debug_f("always-auth key");
if (pkcs11_login(k11, CKU_CONTEXT_SPECIFIC) < 0) {
error("login failed for always-auth key");
return (-1);
@@ -430,7 +430,7 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa,
int rval = -1;
if ((k11 = RSA_get_ex_data(rsa, rsa_idx)) == NULL) {
- error("RSA_get_ex_data failed for rsa %p", rsa);
+ error("RSA_get_ex_data failed");
return (-1);
}
@@ -475,7 +475,7 @@ pkcs11_rsa_start_wrapper(void)
if (!RSA_meth_set1_name(rsa_method, "pkcs11") ||
!RSA_meth_set_priv_enc(rsa_method, pkcs11_rsa_private_encrypt) ||
!RSA_meth_set_priv_dec(rsa_method, pkcs11_rsa_private_decrypt)) {
- error("%s: setup pkcs11 method failed", __func__);
+ error_f("setup pkcs11 method failed");
return (-1);
}
return (0);
@@ -561,7 +561,7 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv,
goto done;
}
if (!ECDSA_SIG_set0(ret, r, s)) {
- error("%s: ECDSA_SIG_set0 failed", __func__);
+ error_f("ECDSA_SIG_set0 failed");
ECDSA_SIG_free(ret);
ret = NULL;
goto done;
@@ -883,7 +883,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
goto fail;
}
if (!RSA_set0_key(rsa, rsa_n, rsa_e, NULL))
- fatal("%s: set key", __func__);
+ fatal_f("set key");
rsa_n = rsa_e = NULL; /* transferred */
if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa))
@@ -973,7 +973,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx,
}
/* Decode DER-encoded cert subject */
- cp = cert_attr[2].pValue;
+ cp = cert_attr[1].pValue;
if ((x509_name = d2i_X509_NAME(NULL, &cp,
cert_attr[1].ulValueLen)) == NULL ||
(subject = X509_NAME_oneline(x509_name, NULL, 0)) == NULL)
@@ -1079,6 +1079,22 @@ have_rsa_key(const RSA *rsa)
}
#endif
+static void
+note_key(struct pkcs11_provider *p, CK_ULONG slotidx, const char *context,
+ struct sshkey *key)
+{
+ char *fp;
+
+ if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
+ SSH_FP_DEFAULT)) == NULL) {
+ error_f("sshkey_fingerprint failed");
+ return;
+ }
+ debug2("%s: provider %s slot %lu: %s %s", context, p->name,
+ (u_long)slotidx, sshkey_type(key), fp);
+ free(fp);
+}
+
/*
* lookup certificates for token in slot identified by slotidx,
* add 'wrapped' public keys to the 'keysp' array and increment nkeys.
@@ -1154,8 +1170,9 @@ pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx,
ck_cert_type);
continue;
}
-
+ note_key(p, slotidx, __func__, key);
if (pkcs11_key_included(keysp, nkeys, key)) {
+ debug2_f("key already included");;
sshkey_free(key);
} else {
/* expand key array and add key */
@@ -1267,8 +1284,9 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
error("failed to fetch key");
continue;
}
-
+ note_key(p, slotidx, __func__, key);
if (pkcs11_key_included(keysp, nkeys, key)) {
+ debug2_f("key already included");;
sshkey_free(key);
} else {
/* expand key array and add key */
@@ -1355,7 +1373,7 @@ pkcs11_rsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv,
&pubKey, &privKey)) != CKR_OK) {
- error("%s: key generation failed: error 0x%lx", __func__, rv);
+ error_f("key generation failed: error 0x%lx", rv);
*err = rv;
return NULL;
}
@@ -1434,12 +1452,12 @@ pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
break;
}
if (!ec_curve_infos[i].name) {
- error("%s: invalid key size %lu", __func__, bits);
+ error_f("invalid key size %lu", bits);
return NULL;
}
if (pkcs11_decode_hex(ec_curve_infos[i].oid_encoded, &ecparams,
&ecparams_size) == -1) {
- error("%s: invalid oid", __func__);
+ error_f("invalid oid");
return NULL;
}
@@ -1472,7 +1490,7 @@ pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx,
if ((rv = f->C_GenerateKeyPair(session, &mech, tpub, npub, tpriv, npriv,
&pubKey, &privKey)) != CKR_OK) {
- error("%s: key generation failed: error 0x%lx", __func__, rv);
+ error_f("key generation failed: error 0x%lx", rv);
*err = rv;
return NULL;
}
@@ -1510,8 +1528,7 @@ pkcs11_register_provider(char *provider_id, char *pin,
*labelsp = NULL;
if (pkcs11_provider_lookup(provider_id) != NULL) {
- debug("%s: provider already registered: %s",
- __func__, provider_id);
+ debug_f("provider already registered: %s", provider_id);
goto fail;
}
/* open shared pkcs11-library */
@@ -1560,8 +1577,7 @@ pkcs11_register_provider(char *provider_id, char *pin,
goto fail;
}
if (p->nslots == 0) {
- debug("%s: provider %s returned no slots", __func__,
- provider_id);
+ debug_f("provider %s returned no slots", provider_id);
ret = -SSH_PKCS11_ERR_NO_SLOTS;
goto fail;
}
@@ -1580,13 +1596,12 @@ pkcs11_register_provider(char *provider_id, char *pin,
if ((rv = f->C_GetTokenInfo(p->slotlist[i], token))
!= CKR_OK) {
error("C_GetTokenInfo for provider %s slot %lu "
- "failed: %lu", provider_id, (unsigned long)i, rv);
+ "failed: %lu", provider_id, (u_long)i, rv);
continue;
}
if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) {
- debug2("%s: ignoring uninitialised token in "
- "provider %s slot %lu", __func__,
- provider_id, (unsigned long)i);
+ debug2_f("ignoring uninitialised token in "
+ "provider %s slot %lu", provider_id, (u_long)i);
continue;
}
rmspace(token->label, sizeof(token->label));
@@ -1668,8 +1683,7 @@ pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp,
pkcs11_provider_unref(p);
}
if (nkeys == 0)
- debug("%s: provider %s returned no keys", __func__,
- provider_id);
+ debug_f("provider %s returned no keys", provider_id);
return (nkeys);
}
@@ -1690,11 +1704,10 @@ pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label,
*err = 0;
if ((p = pkcs11_provider_lookup(provider_id)) != NULL)
- debug("%s: provider \"%s\" available", __func__, provider_id);
+ debug_f("provider \"%s\" available", provider_id);
else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, NULL,
&p, CKU_SO)) < 0) {
- debug("%s: could not register provider %s", __func__,
- provider_id);
+ debug_f("could not register provider %s", provider_id);
goto out;
} else
reset_provider = 1;
@@ -1705,7 +1718,7 @@ pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label,
if ((rv = f->C_SetOperationState(session , pin, strlen(pin),
CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) {
- debug("%s: could not supply SO pin: %lu", __func__, rv);
+ debug_f("could not supply SO pin: %lu", rv);
reset_pin = 0;
} else
reset_pin = 1;
@@ -1714,20 +1727,20 @@ pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label,
case KEY_RSA:
if ((k = pkcs11_rsa_generate_private_key(p, slotidx, label,
bits, keyid, err)) == NULL) {
- debug("%s: failed to generate RSA key", __func__);
+ debug_f("failed to generate RSA key");
goto out;
}
break;
case KEY_ECDSA:
if ((k = pkcs11_ecdsa_generate_private_key(p, slotidx, label,
bits, keyid, err)) == NULL) {
- debug("%s: failed to generate ECDSA key", __func__);
+ debug_f("failed to generate ECDSA key");
goto out;
}
break;
default:
*err = SSH_PKCS11_ERR_GENERIC;
- debug("%s: unknown type %d", __func__, type);
+ debug_f("unknown type %d", type);
goto out;
}
@@ -1762,10 +1775,10 @@ pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx,
*err = 0;
if ((p = pkcs11_provider_lookup(provider_id)) != NULL) {
- debug("%s: using provider \"%s\"", __func__, provider_id);
+ debug_f("using provider \"%s\"", provider_id);
} else if (pkcs11_register_provider(provider_id, pin, NULL, NULL, &p,
CKU_SO) < 0) {
- debug("%s: could not register provider %s", __func__,
+ debug_f("could not register provider %s",
provider_id);
goto out;
} else
@@ -1777,7 +1790,7 @@ pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx,
if ((rv = f->C_SetOperationState(session , pin, strlen(pin),
CK_INVALID_HANDLE, CK_INVALID_HANDLE)) != CKR_OK) {
- debug("%s: could not supply SO pin: %lu", __func__, rv);
+ debug_f("could not supply SO pin: %lu", rv);
reset_pin = 0;
} else
reset_pin = 1;
@@ -1791,8 +1804,8 @@ pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx,
if (pkcs11_find(p, slotidx, attrs, nattrs, &obj) == 0 &&
obj != CK_INVALID_HANDLE) {
if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) {
- debug("%s: could not destroy private key 0x%hhx",
- __func__, keyid);
+ debug_f("could not destroy private key 0x%hhx",
+ keyid);
*err = rv;
goto out;
}
@@ -1813,8 +1826,8 @@ pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx,
sizeof(key_type));
rv = f->C_GetAttributeValue(session, obj, attrs, nattrs);
if (rv != CKR_OK) {
- debug("%s: could not get key type of public key 0x%hhx",
- __func__, keyid);
+ debug_f("could not get key type of public key 0x%hhx",
+ keyid);
*err = rv;
key_type = -1;
}
@@ -1824,8 +1837,7 @@ pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx,
k = pkcs11_fetch_ecdsa_pubkey(p, slotidx, &obj);
if ((rv = f->C_DestroyObject(session, obj)) != CKR_OK) {
- debug("%s: could not destroy public key 0x%hhx",
- __func__, keyid);
+ debug_f("could not destroy public key 0x%hhx", keyid);
*err = rv;
goto out;
}
@@ -1859,7 +1871,8 @@ pkcs11_init(int interactive)
}
int
-pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp)
+pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp,
+ char ***labelsp)
{
error("%s: dlopen() not supported", __func__);
return (-1);
diff --git a/ssh-sk-client.c b/ssh-sk-client.c
index 8d7e6c305..e93259009 100644
--- a/ssh-sk-client.c
+++ b/ssh-sk-client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-sk-client.c,v 1.7 2020/01/23 07:10:22 dtucker Exp $ */
+/* $OpenBSD: ssh-sk-client.c,v 1.9 2021/04/03 06:18:41 djm Exp $ */
/*
* Copyright (c) 2019 Google LLC
*
@@ -47,7 +47,7 @@ static int
start_helper(int *fdp, pid_t *pidp, void (**osigchldp)(int))
{
void (*osigchld)(int);
- int oerrno, pair[2], r = SSH_ERR_INTERNAL_ERROR;
+ int oerrno, pair[2];
pid_t pid;
char *helper, *verbosity = NULL;
@@ -60,8 +60,7 @@ start_helper(int *fdp, pid_t *pidp, void (**osigchldp)(int))
helper = _PATH_SSH_SK_HELPER;
if (access(helper, X_OK) != 0) {
oerrno = errno;
- error("%s: helper \"%s\" unusable: %s", __func__, helper,
- strerror(errno));
+ error_f("helper \"%s\" unusable: %s", helper, strerror(errno));
errno = oerrno;
return SSH_ERR_SYSTEM_ERROR;
}
@@ -87,22 +86,22 @@ start_helper(int *fdp, pid_t *pidp, void (**osigchldp)(int))
if (pid == 0) {
if ((dup2(pair[1], STDIN_FILENO) == -1) ||
(dup2(pair[1], STDOUT_FILENO) == -1)) {
- error("%s: dup2: %s", __func__, ssh_err(r));
+ error_f("dup2: %s", strerror(errno));
_exit(1);
}
close(pair[0]);
close(pair[1]);
closefrom(STDERR_FILENO + 1);
- debug("%s: starting %s %s", __func__, helper,
+ debug_f("starting %s %s", helper,
verbosity == NULL ? "" : verbosity);
execlp(helper, helper, verbosity, (char *)NULL);
- error("%s: execlp: %s", __func__, strerror(errno));
+ error_f("execlp: %s", strerror(errno));
_exit(1);
}
close(pair[1]);
/* success */
- debug3("%s: started pid=%ld", __func__, (long)pid);
+ debug3_f("started pid=%ld", (long)pid);
*fdp = pair[0];
*pidp = pid;
*osigchldp = osigchld;
@@ -114,7 +113,7 @@ reap_helper(pid_t pid)
{
int status, oerrno;
- debug3("%s: pid=%ld", __func__, (long)pid);
+ debug3_f("pid=%ld", (long)pid);
errno = 0;
while (waitpid(pid, &status, 0) == -1) {
@@ -123,15 +122,15 @@ reap_helper(pid_t pid)
continue;
}
oerrno = errno;
- error("%s: waitpid: %s", __func__, strerror(errno));
+ error_f("waitpid: %s", strerror(errno));
errno = oerrno;
return SSH_ERR_SYSTEM_ERROR;
}
if (!WIFEXITED(status)) {
- error("%s: helper exited abnormally", __func__);
+ error_f("helper exited abnormally");
return SSH_ERR_AGENT_FAILURE;
} else if (WEXITSTATUS(status) != 0) {
- error("%s: helper exited with non-zero exit status", __func__);
+ error_f("helper exited with non-zero exit status");
return SSH_ERR_AGENT_FAILURE;
}
return 0;
@@ -158,40 +157,40 @@ client_converse(struct sshbuf *msg, struct sshbuf **respp, u_int type)
/* Request preamble: type, log_on_stderr, log_level */
ll = log_level_get();
if ((r = sshbuf_put_u32(req, type)) != 0 ||
- (r = sshbuf_put_u8(req, log_is_on_stderr() != 0)) != 0 ||
- (r = sshbuf_put_u32(req, ll < 0 ? 0 : ll)) != 0 ||
- (r = sshbuf_putb(req, msg)) != 0) {
- error("%s: build: %s", __func__, ssh_err(r));
+ (r = sshbuf_put_u8(req, log_is_on_stderr() != 0)) != 0 ||
+ (r = sshbuf_put_u32(req, ll < 0 ? 0 : ll)) != 0 ||
+ (r = sshbuf_putb(req, msg)) != 0) {
+ error_fr(r, "compose");
goto out;
}
if ((r = ssh_msg_send(fd, SSH_SK_HELPER_VERSION, req)) != 0) {
- error("%s: send: %s", __func__, ssh_err(r));
+ error_fr(r, "send");
goto out;
}
if ((r = ssh_msg_recv(fd, resp)) != 0) {
- error("%s: receive: %s", __func__, ssh_err(r));
+ error_fr(r, "receive");
goto out;
}
if ((r = sshbuf_get_u8(resp, &version)) != 0) {
- error("%s: parse version: %s", __func__, ssh_err(r));
+ error_fr(r, "parse version");
goto out;
}
if (version != SSH_SK_HELPER_VERSION) {
- error("%s: unsupported version: got %u, expected %u",
- __func__, version, SSH_SK_HELPER_VERSION);
+ error_f("unsupported version: got %u, expected %u",
+ version, SSH_SK_HELPER_VERSION);
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
if ((r = sshbuf_get_u32(resp, &rtype)) != 0) {
- error("%s: parse message type: %s", __func__, ssh_err(r));
+ error_fr(r, "parse message type");
goto out;
}
if (rtype == SSH_SK_HELPER_ERROR) {
if ((r = sshbuf_get_u32(resp, &rerr)) != 0) {
- error("%s: parse error: %s", __func__, ssh_err(r));
+ error_fr(r, "parse");
goto out;
}
- debug("%s: helper returned error -%u", __func__, rerr);
+ debug_f("helper returned error -%u", rerr);
/* OpenSSH error values are negative; encoded as -err on wire */
if (rerr == 0 || rerr >= INT_MAX)
r = SSH_ERR_INTERNAL_ERROR;
@@ -199,8 +198,8 @@ client_converse(struct sshbuf *msg, struct sshbuf **respp, u_int type)
r = -(int)rerr;
goto out;
} else if (rtype != type) {
- error("%s: helper returned incorrect message type %u, "
- "expecting %u", __func__, rtype, type);
+ error_f("helper returned incorrect message type %u, "
+ "expecting %u", rtype, type);
r = SSH_ERR_INTERNAL_ERROR;
goto out;
}
@@ -250,7 +249,7 @@ sshsk_sign(const char *provider, struct sshkey *key,
}
if ((r = sshkey_private_serialize(key, kbuf)) != 0) {
- error("%s: serialize private key: %s", __func__, ssh_err(r));
+ error_fr(r, "encode key");
goto out;
}
if ((r = sshbuf_put_stringb(req, kbuf)) != 0 ||
@@ -259,13 +258,13 @@ sshsk_sign(const char *provider, struct sshkey *key,
(r = sshbuf_put_cstring(req, NULL)) != 0 || /* alg */
(r = sshbuf_put_u32(req, compat)) != 0 ||
(r = sshbuf_put_cstring(req, pin)) != 0) {
- error("%s: compose: %s", __func__, ssh_err(r));
+ error_fr(r, "compose");
goto out;
}
if ((fp = sshkey_fingerprint(key, SSH_FP_HASH_DEFAULT,
SSH_FP_DEFAULT)) == NULL) {
- error("%s: sshkey_fingerprint failed", __func__);
+ error_f("sshkey_fingerprint failed");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
@@ -273,12 +272,12 @@ sshsk_sign(const char *provider, struct sshkey *key,
goto out;
if ((r = sshbuf_get_string(resp, sigp, lenp)) != 0) {
- error("%s: parse signature: %s", __func__, ssh_err(r));
+ error_fr(r, "parse signature");
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
if (sshbuf_len(resp) != 0) {
- error("%s: trailing data in response", __func__);
+ error_f("trailing data in response");
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
@@ -334,7 +333,7 @@ sshsk_enroll(int type, const char *provider_path, const char *device,
(r = sshbuf_put_u8(req, flags)) != 0 ||
(r = sshbuf_put_cstring(req, pin)) != 0 ||
(r = sshbuf_put_stringb(req, challenge_buf)) != 0) {
- error("%s: compose: %s", __func__, ssh_err(r));
+ error_fr(r, "compose");
goto out;
}
@@ -343,21 +342,21 @@ sshsk_enroll(int type, const char *provider_path, const char *device,
if ((r = sshbuf_get_stringb(resp, kbuf)) != 0 ||
(r = sshbuf_get_stringb(resp, abuf)) != 0) {
- error("%s: parse signature: %s", __func__, ssh_err(r));
+ error_fr(r, "parse");
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
if (sshbuf_len(resp) != 0) {
- error("%s: trailing data in response", __func__);
+ error_f("trailing data in response");
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
if ((r = sshkey_private_deserialize(kbuf, &key)) != 0) {
- error("Unable to parse private key: %s", ssh_err(r));
+ error_fr(r, "encode");
goto out;
}
if (attest != NULL && (r = sshbuf_putb(attest, abuf)) != 0) {
- error("%s: buffer error: %s", __func__, ssh_err(r));
+ error_fr(r, "encode attestation information");
goto out;
}
@@ -398,7 +397,7 @@ sshsk_load_resident(const char *provider_path, const char *device,
if ((r = sshbuf_put_cstring(req, provider_path)) != 0 ||
(r = sshbuf_put_cstring(req, device)) != 0 ||
(r = sshbuf_put_cstring(req, pin)) != 0) {
- error("%s: compose: %s", __func__, ssh_err(r));
+ error_fr(r, "compose");
goto out;
}
@@ -409,21 +408,21 @@ sshsk_load_resident(const char *provider_path, const char *device,
/* key, comment */
if ((r = sshbuf_get_stringb(resp, kbuf)) != 0 ||
(r = sshbuf_get_cstring(resp, NULL, NULL)) != 0) {
- error("%s: parse signature: %s", __func__, ssh_err(r));
+ error_fr(r, "parse signature");
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
if ((r = sshkey_private_deserialize(kbuf, &key)) != 0) {
- error("Unable to parse private key: %s", ssh_err(r));
+ error_fr(r, "decode key");
goto out;
}
if ((tmp = recallocarray(keys, nkeys, nkeys + 1,
sizeof(*keys))) == NULL) {
- error("%s: recallocarray keys failed", __func__);
+ error_f("recallocarray keys failed");
goto out;
}
- debug("%s: keys[%zu]: %s %s", __func__,
- nkeys, sshkey_type(key), key->sk_application);
+ debug_f("keys[%zu]: %s %s", nkeys, sshkey_type(key),
+ key->sk_application);
keys = tmp;
keys[nkeys++] = key;
key = NULL;
diff --git a/ssh-sk-helper.c b/ssh-sk-helper.c
index 2f93ad716..21a08919d 100644
--- a/ssh-sk-helper.c
+++ b/ssh-sk-helper.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-sk-helper.c,v 1.9 2020/01/25 23:13:09 djm Exp $ */
+/* $OpenBSD: ssh-sk-helper.c,v 1.11 2020/10/18 11:32:02 djm Exp $ */
/*
* Copyright (c) 2019 Google LLC
*
@@ -67,7 +67,7 @@ reply_error(int r, char *fmt, ...)
free(msg);
if (r >= 0)
- fatal("%s: invalid error code %d", __func__, r);
+ fatal_f("invalid error code %d", r);
if ((resp = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __progname);
@@ -93,12 +93,12 @@ process_sign(struct sshbuf *req)
{
int r = SSH_ERR_INTERNAL_ERROR;
struct sshbuf *resp, *kbuf;
- struct sshkey *key;
+ struct sshkey *key = NULL;
uint32_t compat;
const u_char *message;
- u_char *sig;
- size_t msglen, siglen;
- char *provider, *pin;
+ u_char *sig = NULL;
+ size_t msglen, siglen = 0;
+ char *provider = NULL, *pin = NULL;
if ((r = sshbuf_froms(req, &kbuf)) != 0 ||
(r = sshbuf_get_cstring(req, &provider, NULL)) != 0 ||
@@ -106,17 +106,19 @@ process_sign(struct sshbuf *req)
(r = sshbuf_get_cstring(req, NULL, NULL)) != 0 || /* alg */
(r = sshbuf_get_u32(req, &compat)) != 0 ||
(r = sshbuf_get_cstring(req, &pin, NULL)) != 0)
- fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ fatal_r(r, "%s: parse", __progname);
if (sshbuf_len(req) != 0)
fatal("%s: trailing data in request", __progname);
if ((r = sshkey_private_deserialize(kbuf, &key)) != 0)
- fatal("Unable to parse private key: %s", ssh_err(r));
- if (!sshkey_is_sk(key))
- fatal("Unsupported key type %s", sshkey_ssh_name(key));
+ fatal_r(r, "%s: Unable to parse private key", __progname);
+ if (!sshkey_is_sk(key)) {
+ fatal("%s: Unsupported key type %s",
+ __progname, sshkey_ssh_name(key));
+ }
- debug("%s: ready to sign with key %s, provider %s: "
- "msg len %zu, compat 0x%lx", __progname, sshkey_type(key),
+ debug_f("ready to sign with key %s, provider %s: "
+ "msg len %zu, compat 0x%lx", sshkey_type(key),
provider, msglen, (u_long)compat);
null_empty(&pin);
@@ -132,10 +134,13 @@ process_sign(struct sshbuf *req)
if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_SIGN)) != 0 ||
(r = sshbuf_put_string(resp, sig, siglen)) != 0)
- fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ fatal_r(r, "%s: compose", __progname);
out:
+ sshkey_free(key);
sshbuf_free(kbuf);
free(provider);
+ if (sig != NULL)
+ freezero(sig, siglen);
if (pin != NULL)
freezero(pin, strlen(pin));
return resp;
@@ -163,7 +168,7 @@ process_enroll(struct sshbuf *req)
(r = sshbuf_get_u8(req, &flags)) != 0 ||
(r = sshbuf_get_cstring(req, &pin, NULL)) != 0 ||
(r = sshbuf_froms(req, &challenge)) != 0)
- fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ fatal_r(r, "%s: parse", __progname);
if (sshbuf_len(req) != 0)
fatal("%s: trailing data in request", __progname);
@@ -186,11 +191,11 @@ process_enroll(struct sshbuf *req)
if ((resp = sshbuf_new()) == NULL)
fatal("%s: sshbuf_new failed", __progname);
if ((r = sshkey_private_serialize(key, kbuf)) != 0)
- fatal("%s: serialize private key: %s", __progname, ssh_err(r));
+ fatal_r(r, "%s: encode key", __progname);
if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_ENROLL)) != 0 ||
(r = sshbuf_put_stringb(resp, kbuf)) != 0 ||
(r = sshbuf_put_stringb(resp, attest)) != 0)
- fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ fatal_r(r, "%s: compose", __progname);
out:
sshkey_free(key);
@@ -220,7 +225,7 @@ process_load_resident(struct sshbuf *req)
if ((r = sshbuf_get_cstring(req, &provider, NULL)) != 0 ||
(r = sshbuf_get_cstring(req, &device, NULL)) != 0 ||
(r = sshbuf_get_cstring(req, &pin, NULL)) != 0)
- fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ fatal_r(r, "%s: parse", __progname);
if (sshbuf_len(req) != 0)
fatal("%s: trailing data in request", __progname);
@@ -238,18 +243,17 @@ process_load_resident(struct sshbuf *req)
fatal("%s: sshbuf_new failed", __progname);
if ((r = sshbuf_put_u32(resp, SSH_SK_HELPER_LOAD_RESIDENT)) != 0)
- fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ fatal_r(r, "%s: compose", __progname);
for (i = 0; i < nkeys; i++) {
- debug("%s: key %zu %s %s", __func__, i,
- sshkey_type(keys[i]), keys[i]->sk_application);
+ debug_f("key %zu %s %s", i, sshkey_type(keys[i]),
+ keys[i]->sk_application);
sshbuf_reset(kbuf);
if ((r = sshkey_private_serialize(keys[i], kbuf)) != 0)
- fatal("%s: serialize private key: %s",
- __progname, ssh_err(r));
+ fatal_r(r, "%s: encode key", __progname);
if ((r = sshbuf_put_stringb(resp, kbuf)) != 0 ||
(r = sshbuf_put_cstring(resp, "")) != 0) /* comment */
- fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ fatal_r(r, "%s: compose key", __progname);
}
out:
@@ -308,10 +312,10 @@ main(int argc, char **argv)
if (ssh_msg_recv(in, req) < 0)
fatal("ssh_msg_recv failed");
close(in);
- debug("%s: received message len %zu", __progname, sshbuf_len(req));
+ debug_f("received message len %zu", sshbuf_len(req));
if ((r = sshbuf_get_u8(req, &version)) != 0)
- fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ fatal_r(r, "%s: parse version", __progname);
if (version != SSH_SK_HELPER_VERSION) {
fatal("unsupported version: received %d, expected %d",
version, SSH_SK_HELPER_VERSION);
@@ -320,7 +324,7 @@ main(int argc, char **argv)
if ((r = sshbuf_get_u32(req, &rtype)) != 0 ||
(r = sshbuf_get_u8(req, &log_stderr)) != 0 ||
(r = sshbuf_get_u32(req, &ll)) != 0)
- fatal("%s: buffer error: %s", __progname, ssh_err(r));
+ fatal_r(r, "%s: parse", __progname);
if (!vflag && log_level_name((LogLevel)ll) != NULL)
log_init(__progname, (LogLevel)ll, log_facility, log_stderr);
@@ -339,7 +343,7 @@ main(int argc, char **argv)
fatal("%s: unsupported request type %u", __progname, rtype);
}
sshbuf_free(req);
- debug("%s: reply len %zu", __progname, sshbuf_len(resp));
+ debug_f("reply len %zu", sshbuf_len(resp));
if (ssh_msg_send(out, SSH_SK_HELPER_VERSION, resp) == -1)
fatal("ssh_msg_send failed");
diff --git a/ssh-sk.c b/ssh-sk.c
index 1afb205f8..d254e77f9 100644
--- a/ssh-sk.c
+++ b/ssh-sk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-sk.c,v 1.30 2020/04/28 04:02:29 djm Exp $ */
+/* $OpenBSD: ssh-sk.c,v 1.35 2021/02/26 00:16:58 djm Exp $ */
/*
* Copyright (c) 2019 Google LLC
*
@@ -105,11 +105,11 @@ sshsk_open(const char *path)
return NULL;
}
if ((ret = calloc(1, sizeof(*ret))) == NULL) {
- error("%s: calloc failed", __func__);
+ error_f("calloc failed");
return NULL;
}
if ((ret->path = strdup(path)) == NULL) {
- error("%s: strdup failed", __func__);
+ error_f("strdup failed");
goto fail;
}
/* Skip the rest if we're using the linked in middleware */
@@ -134,8 +134,8 @@ sshsk_open(const char *path)
goto fail;
}
version = ret->sk_api_version();
- debug("%s: provider %s implements version 0x%08lx", __func__,
- ret->path, (u_long)version);
+ debug_f("provider %s implements version 0x%08lx", ret->path,
+ (u_long)version);
if ((version & SSH_SK_VERSION_MAJOR_MASK) != SSH_SK_VERSION_MAJOR) {
error("Provider \"%s\" implements unsupported "
"version 0x%08lx (supported: 0x%08lx)",
@@ -174,6 +174,7 @@ sshsk_free_enroll_response(struct sk_enroll_response *r)
freezero(r->public_key, r->public_key_len);
freezero(r->signature, r->signature_len);
freezero(r->attestation_cert, r->attestation_cert_len);
+ freezero(r->authdata, r->authdata_len);
freezero(r, sizeof(*r));
}
@@ -199,7 +200,7 @@ sshsk_ecdsa_assemble(struct sk_enroll_response *resp, struct sshkey **keyp)
*keyp = NULL;
if ((key = sshkey_new(KEY_ECDSA_SK)) == NULL) {
- error("%s: sshkey_new failed", __func__);
+ error_f("sshkey_new failed");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
@@ -207,17 +208,17 @@ sshsk_ecdsa_assemble(struct sk_enroll_response *resp, struct sshkey **keyp)
if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL ||
(q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL ||
(b = sshbuf_new()) == NULL) {
- error("%s: allocation failed", __func__);
+ error_f("allocation failed");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((r = sshbuf_put_string(b,
resp->public_key, resp->public_key_len)) != 0) {
- error("%s: buffer error: %s", __func__, ssh_err(r));
+ error_fr(r, "sshbuf_put_string");
goto out;
}
if ((r = sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa))) != 0) {
- error("%s: parse key: %s", __func__, ssh_err(r));
+ error_fr(r, "parse");
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
@@ -228,7 +229,7 @@ sshsk_ecdsa_assemble(struct sk_enroll_response *resp, struct sshkey **keyp)
}
if (EC_KEY_set_public_key(key->ecdsa, q) != 1) {
/* XXX assume it is a allocation error */
- error("%s: allocation failed", __func__);
+ error_f("allocation failed");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
@@ -252,17 +253,17 @@ sshsk_ed25519_assemble(struct sk_enroll_response *resp, struct sshkey **keyp)
*keyp = NULL;
if (resp->public_key_len != ED25519_PK_SZ) {
- error("%s: invalid size: %zu", __func__, resp->public_key_len);
+ error_f("invalid size: %zu", resp->public_key_len);
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
if ((key = sshkey_new(KEY_ED25519_SK)) == NULL) {
- error("%s: sshkey_new failed", __func__);
+ error_f("sshkey_new failed");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((key->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
- error("%s: malloc failed", __func__);
+ error_f("malloc failed");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
@@ -287,7 +288,7 @@ sshsk_key_from_response(int alg, const char *application, uint8_t flags,
/* Check response validity */
if (resp->public_key == NULL || resp->key_handle == NULL) {
- error("%s: sk_enroll response invalid", __func__);
+ error_f("sk_enroll response invalid");
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
@@ -303,25 +304,25 @@ sshsk_key_from_response(int alg, const char *application, uint8_t flags,
goto out;
break;
default:
- error("%s: unsupported algorithm %d", __func__, alg);
+ error_f("unsupported algorithm %d", alg);
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
key->sk_flags = flags;
if ((key->sk_key_handle = sshbuf_new()) == NULL ||
(key->sk_reserved = sshbuf_new()) == NULL) {
- error("%s: allocation failed", __func__);
+ error_f("allocation failed");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((key->sk_application = strdup(application)) == NULL) {
- error("%s: strdup application failed", __func__);
+ error_f("strdup application failed");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((r = sshbuf_put(key->sk_key_handle, resp->key_handle,
resp->key_handle_len)) != 0) {
- error("%s: buffer error: %s", __func__, ssh_err(r));
+ error_fr(r, "put key handle");
goto out;
}
/* success */
@@ -373,18 +374,18 @@ sshsk_add_option(struct sk_option ***optsp, size_t *noptsp,
if ((opts = recallocarray(opts, nopts, nopts + 2, /* extra for NULL */
sizeof(*opts))) == NULL) {
- error("%s: array alloc failed", __func__);
+ error_f("array alloc failed");
return SSH_ERR_ALLOC_FAIL;
}
*optsp = opts;
*noptsp = nopts + 1;
if ((opts[nopts] = calloc(1, sizeof(**opts))) == NULL) {
- error("%s: alloc failed", __func__);
+ error_f("alloc failed");
return SSH_ERR_ALLOC_FAIL;
}
if ((opts[nopts]->name = strdup(name)) == NULL ||
(opts[nopts]->value = strdup(value)) == NULL) {
- error("%s: alloc failed", __func__);
+ error_f("alloc failed");
return SSH_ERR_ALLOC_FAIL;
}
opts[nopts]->required = required;
@@ -419,6 +420,31 @@ make_options(const char *device, const char *user_id,
return ret;
}
+
+static int
+fill_attestation_blob(const struct sk_enroll_response *resp,
+ struct sshbuf *attest)
+{
+ int r;
+
+ if (attest == NULL)
+ return 0; /* nothing to do */
+ if ((r = sshbuf_put_cstring(attest, "ssh-sk-attest-v01")) != 0 ||
+ (r = sshbuf_put_string(attest,
+ resp->attestation_cert, resp->attestation_cert_len)) != 0 ||
+ (r = sshbuf_put_string(attest,
+ resp->signature, resp->signature_len)) != 0 ||
+ (r = sshbuf_put_string(attest,
+ resp->authdata, resp->authdata_len)) != 0 ||
+ (r = sshbuf_put_u32(attest, 0)) != 0 || /* resvd flags */
+ (r = sshbuf_put_string(attest, NULL, 0)) != 0 /* resvd */) {
+ error_fr(r, "compose");
+ return r;
+ }
+ /* success */
+ return 0;
+}
+
int
sshsk_enroll(int type, const char *provider_path, const char *device,
const char *application, const char *userid, uint8_t flags,
@@ -435,8 +461,8 @@ sshsk_enroll(int type, const char *provider_path, const char *device,
int r = SSH_ERR_INTERNAL_ERROR;
int alg;
- debug("%s: provider \"%s\", device \"%s\", application \"%s\", "
- "userid \"%s\", flags 0x%02x, challenge len %zu%s", __func__,
+ debug_f("provider \"%s\", device \"%s\", application \"%s\", "
+ "userid \"%s\", flags 0x%02x, challenge len %zu%s",
provider_path, device, application, userid, flags,
challenge_buf == NULL ? 0 : sshbuf_len(challenge_buf),
(pin != NULL && *pin != '\0') ? " with-pin" : "");
@@ -458,22 +484,22 @@ sshsk_enroll(int type, const char *provider_path, const char *device,
alg = SSH_SK_ED25519;
break;
default:
- error("%s: unsupported key type", __func__);
+ error_f("unsupported key type");
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
if (provider_path == NULL) {
- error("%s: missing provider", __func__);
+ error_f("missing provider");
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
if (application == NULL || *application == '\0') {
- error("%s: missing application", __func__);
+ error_f("missing application");
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
if (challenge_buf == NULL) {
- debug("%s: using random challenge", __func__);
+ debug_f("using random challenge");
arc4random_buf(randchall, sizeof(randchall));
challenge = randchall;
challenge_len = sizeof(randchall);
@@ -484,8 +510,7 @@ sshsk_enroll(int type, const char *provider_path, const char *device,
} else {
challenge = sshbuf_ptr(challenge_buf);
challenge_len = sshbuf_len(challenge_buf);
- debug3("%s: using explicit challenge len=%zd",
- __func__, challenge_len);
+ debug3_f("using explicit challenge len=%zd", challenge_len);
}
if ((skp = sshsk_open(provider_path)) == NULL) {
r = SSH_ERR_INVALID_FORMAT; /* XXX sshsk_open return code? */
@@ -495,8 +520,7 @@ sshsk_enroll(int type, const char *provider_path, const char *device,
/* enroll key */
if ((r = skp->sk_enroll(alg, challenge, challenge_len, application,
flags, pin, opts, &resp)) != 0) {
- debug("%s: provider \"%s\" returned failure %d", __func__,
- provider_path, r);
+ debug_f("provider \"%s\" failure %d", provider_path, r);
r = skerr_to_ssherr(r);
goto out;
}
@@ -506,19 +530,9 @@ sshsk_enroll(int type, const char *provider_path, const char *device,
goto out;
/* Optionally fill in the attestation information */
- if (attest != NULL) {
- if ((r = sshbuf_put_cstring(attest,
- "ssh-sk-attest-v00")) != 0 ||
- (r = sshbuf_put_string(attest,
- resp->attestation_cert, resp->attestation_cert_len)) != 0 ||
- (r = sshbuf_put_string(attest,
- resp->signature, resp->signature_len)) != 0 ||
- (r = sshbuf_put_u32(attest, 0)) != 0 || /* resvd flags */
- (r = sshbuf_put_string(attest, NULL, 0)) != 0 /* resvd */) {
- error("%s: buffer error: %s", __func__, ssh_err(r));
- goto out;
- }
- }
+ if ((r = fill_attestation_blob(resp, attest)) != 0)
+ goto out;
+
/* success */
*keyp = key;
key = NULL; /* transferred */
@@ -541,7 +555,7 @@ sshsk_ecdsa_sig(struct sk_sign_response *resp, struct sshbuf *sig)
/* Check response validity */
if (resp->sig_r == NULL || resp->sig_s == NULL) {
- error("%s: sk_sign response invalid", __func__);
+ error_f("sk_sign response invalid");
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
@@ -554,13 +568,13 @@ sshsk_ecdsa_sig(struct sk_sign_response *resp, struct sshbuf *sig)
resp->sig_r, resp->sig_r_len)) != 0 ||
(r = sshbuf_put_bignum2_bytes(inner_sig,
resp->sig_s, resp->sig_s_len)) != 0) {
- debug("%s: buffer error: %s", __func__, ssh_err(r));
+ error_fr(r, "compose inner");
goto out;
}
if ((r = sshbuf_put_stringb(sig, inner_sig)) != 0 ||
(r = sshbuf_put_u8(sig, resp->flags)) != 0 ||
(r = sshbuf_put_u32(sig, resp->counter)) != 0) {
- debug("%s: buffer error: %s", __func__, ssh_err(r));
+ error_fr(r, "compose");
goto out;
}
#ifdef DEBUG_SK
@@ -585,7 +599,7 @@ sshsk_ed25519_sig(struct sk_sign_response *resp, struct sshbuf *sig)
/* Check response validity */
if (resp->sig_r == NULL) {
- error("%s: sk_sign response invalid", __func__);
+ error_f("sk_sign response invalid");
r = SSH_ERR_INVALID_FORMAT;
goto out;
}
@@ -593,7 +607,7 @@ sshsk_ed25519_sig(struct sk_sign_response *resp, struct sshbuf *sig)
resp->sig_r, resp->sig_r_len)) != 0 ||
(r = sshbuf_put_u8(sig, resp->flags)) != 0 ||
(r = sshbuf_put_u32(sig, resp->counter)) != 0) {
- debug("%s: buffer error: %s", __func__, ssh_err(r));
+ error_fr(r, "compose");
goto out;
}
#ifdef DEBUG_SK
@@ -617,7 +631,7 @@ sshsk_sign(const char *provider_path, struct sshkey *key,
struct sshbuf *inner_sig = NULL, *sig = NULL;
struct sk_option **opts = NULL;
- debug("%s: provider \"%s\", key %s, flags 0x%02x%s", __func__,
+ debug_f("provider \"%s\", key %s, flags 0x%02x%s",
provider_path, sshkey_type(key), key->sk_flags,
(pin != NULL && *pin != '\0') ? " with-pin" : "");
@@ -648,11 +662,16 @@ sshsk_sign(const char *provider_path, struct sshkey *key,
r = SSH_ERR_INVALID_FORMAT; /* XXX sshsk_open return code? */
goto out;
}
-
+#ifdef DEBUG_SK
+ fprintf(stderr, "%s: sk_flags = 0x%02x, sk_application = \"%s\"\n",
+ __func__, key->sk_flags, key->sk_application);
+ fprintf(stderr, "%s: sk_key_handle:\n", __func__);
+ sshbuf_dump(key->sk_key_handle, stderr);
+#endif
if ((r = skp->sk_sign(alg, data, datalen, key->sk_application,
sshbuf_ptr(key->sk_key_handle), sshbuf_len(key->sk_key_handle),
key->sk_flags, pin, opts, &resp)) != 0) {
- debug("%s: sk_sign failed with code %d", __func__, r);
+ debug_f("sk_sign failed with code %d", r);
r = skerr_to_ssherr(r);
goto out;
}
@@ -662,7 +681,7 @@ sshsk_sign(const char *provider_path, struct sshkey *key,
goto out;
}
if ((r = sshbuf_put_cstring(sig, sshkey_ssh_name_plain(key))) != 0) {
- debug("%s: buffer error (outer): %s", __func__, ssh_err(r));
+ error_fr(r, "compose outer");
goto out;
}
switch (type) {
@@ -680,8 +699,8 @@ sshsk_sign(const char *provider_path, struct sshkey *key,
#ifdef DEBUG_SK
fprintf(stderr, "%s: sig_flags = 0x%02x, sig_counter = %u\n",
__func__, resp->flags, resp->counter);
- fprintf(stderr, "%s: hashed message:\n", __func__);
- sshbuf_dump_data(message, sizeof(message), stderr);
+ fprintf(stderr, "%s: data to sign:\n", __func__);
+ sshbuf_dump_data(data, datalen, stderr);
fprintf(stderr, "%s: sigbuf:\n", __func__);
sshbuf_dump(sig, stderr);
#endif
@@ -736,7 +755,7 @@ sshsk_load_resident(const char *provider_path, const char *device,
uint8_t flags;
struct sk_option **opts = NULL;
- debug("%s: provider \"%s\"%s", __func__, provider_path,
+ debug_f("provider \"%s\"%s", provider_path,
(pin != NULL && *pin != '\0') ? ", have-pin": "");
if (keysp == NULL || nkeysp == NULL)
@@ -756,9 +775,8 @@ sshsk_load_resident(const char *provider_path, const char *device,
goto out;
}
for (i = 0; i < nrks; i++) {
- debug3("%s: rk %zu: slot = %zu, alg = %d, application = \"%s\"",
- __func__, i, rks[i]->slot, rks[i]->alg,
- rks[i]->application);
+ debug3_f("rk %zu: slot = %zu, alg = %d, application = \"%s\"",
+ i, rks[i]->slot, rks[i]->alg, rks[i]->application);
/* XXX need better filter here */
if (strncmp(rks[i]->application, "ssh:", 4) != 0)
continue;
@@ -769,14 +787,15 @@ sshsk_load_resident(const char *provider_path, const char *device,
default:
continue;
}
- /* XXX where to get flags? */
flags = SSH_SK_USER_PRESENCE_REQD|SSH_SK_RESIDENT_KEY;
+ if ((rks[i]->flags & SSH_SK_USER_VERIFICATION_REQD))
+ flags |= SSH_SK_USER_VERIFICATION_REQD;
if ((r = sshsk_key_from_response(rks[i]->alg,
rks[i]->application, flags, &rks[i]->key, &key)) != 0)
goto out;
if ((tmp = recallocarray(keys, nkeys, nkeys + 1,
sizeof(*tmp))) == NULL) {
- error("%s: recallocarray failed", __func__);
+ error_f("recallocarray failed");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
diff --git a/ssh-xmss.c b/ssh-xmss.c
index ccd4c7600..7bd3a96a3 100644
--- a/ssh-xmss.c
+++ b/ssh-xmss.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-xmss.c,v 1.2 2020/02/26 13:40:09 jsg Exp $*/
+/* $OpenBSD: ssh-xmss.c,v 1.4 2020/10/19 22:49:23 dtucker Exp $*/
/*
* Copyright (c) 2017 Stefan-Lukas Gazdag.
* Copyright (c) 2017 Markus Friedl.
@@ -62,7 +62,7 @@ ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
smlen = slen = datalen + required_siglen;
if ((sig = malloc(slen)) == NULL)
return SSH_ERR_ALLOC_FAIL;
- if ((r = sshkey_xmss_get_state(key, error)) != 0)
+ if ((r = sshkey_xmss_get_state(key, 1)) != 0)
goto out;
if ((ret = xmss_sign(key->xmss_sk, sshkey_xmss_bds_state(key), sig, &smlen,
data, datalen, sshkey_xmss_params(key))) != 0 || smlen <= datalen) {
@@ -90,7 +90,7 @@ ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
/* success */
r = 0;
out:
- if ((ret = sshkey_xmss_update_state(key, error)) != 0) {
+ if ((ret = sshkey_xmss_update_state(key, 1)) != 0) {
/* discard signature since we cannot update the state */
if (r == 0 && sigp != NULL && *sigp != NULL) {
explicit_bzero(*sigp, len);
@@ -164,8 +164,7 @@ ssh_xmss_verify(const struct sshkey *key,
memcpy(sm+len, data, datalen);
if ((ret = xmss_sign_open(m, &mlen, sm, smlen,
key->xmss_pk, sshkey_xmss_params(key))) != 0) {
- debug2("%s: crypto_sign_xmss_open failed: %d",
- __func__, ret);
+ debug2_f("xmss_sign_open failed: %d", ret);
}
if (ret != 0 || mlen != datalen) {
r = SSH_ERR_SIGNATURE_INVALID;
diff --git a/ssh.1 b/ssh.1
index dce5f404b..7efb23828 100644
--- a/ssh.1
+++ b/ssh.1
@@ -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.1,v 1.412 2020/04/17 03:34:42 djm Exp $
-.Dd $Mdocdate: April 17 2020 $
+.\" $OpenBSD: ssh.1,v 1.427 2021/09/10 10:26:02 dtucker Exp $
+.Dd $Mdocdate: September 10 2021 $
.Dt SSH 1
.Os
.Sh NAME
@@ -65,7 +65,7 @@
.Op Fl W Ar host : Ns Ar port
.Op Fl w Ar local_tun Ns Op : Ns Ar remote_tun
.Ar destination
-.Op Ar command
+.Op Ar command Op Ar argument ...
.Sh DESCRIPTION
.Nm
(SSH client) is a program for logging into a remote machine and for
@@ -88,13 +88,18 @@ or a URI of the form
.No ssh:// Oo user @ Oc hostname Op : port .
.Sm on
The user must prove
-his/her identity to the remote machine using one of several methods
+their identity to the remote machine using one of several methods
(see below).
.Pp
If a
.Ar command
is specified,
-it is executed on the remote host instead of a login shell.
+it will be executed on the remote host instead of a login shell.
+A complete command line may be specified as
+.Ar command ,
+or it may have additional arguments.
+If supplied, the arguments will be appended to the command, separated by
+spaces, before it is sent to the server to be executed.
.Pp
The options are as follows:
.Pp
@@ -259,6 +264,11 @@ then a client started with
.Fl f
will wait for all remote port forwards to be successfully established
before placing itself in the background.
+Refer to the description of
+.Cm ForkAfterAuthentication
+in
+.Xr ssh_config 5
+for details.
.Pp
.It Fl G
Causes
@@ -283,6 +293,10 @@ authentication.
.It Fl i Ar identity_file
Selects a file from which the identity (private key) for
public key authentication is read.
+You can also specify a public key file to use the corresponding
+private key that is loaded in
+.Xr ssh-agent 1
+when the private key file is not present locally.
The default is
.Pa ~/.ssh/id_dsa ,
.Pa ~/.ssh/id_ecdsa ,
@@ -425,6 +439,11 @@ keyword for more information.
.It Fl N
Do not execute a remote command.
This is useful for just forwarding ports.
+Refer to the description of
+.Cm SessionType
+in
+.Xr ssh_config 5
+for details.
.Pp
.It Fl n
Redirects stdin from
@@ -446,6 +465,11 @@ program will be put in the background.
needs to ask for a password or passphrase; see also the
.Fl f
option.)
+Refer to the description of
+.Cm StdinNull
+in
+.Xr ssh_config 5
+for details.
.Pp
.It Fl O Ar ctl_cmd
Control an active connection multiplexing master process.
@@ -485,7 +509,6 @@ For full details of the options listed below, and their possible values, see
.It CanonicalizePermittedCNAMEs
.It CASignatureAlgorithms
.It CertificateFile
-.It ChallengeResponseAuthentication
.It CheckHostIP
.It Ciphers
.It ClearAllForwardings
@@ -499,6 +522,7 @@ For full details of the options listed below, and their possible values, see
.It EscapeChar
.It ExitOnForwardFailure
.It FingerprintHash
+.It ForkAfterAuthentication
.It ForwardAgent
.It ForwardX11
.It ForwardX11Timeout
@@ -509,8 +533,8 @@ For full details of the options listed below, and their possible values, see
.It GSSAPIDelegateCredentials
.It HashKnownHosts
.It Host
+.It HostbasedAcceptedAlgorithms
.It HostbasedAuthentication
-.It HostbasedKeyTypes
.It HostKeyAlgorithms
.It HostKeyAlias
.It Hostname
@@ -521,6 +545,7 @@ For full details of the options listed below, and their possible values, see
.It KbdInteractiveAuthentication
.It KbdInteractiveDevices
.It KexAlgorithms
+.It KnownHostsCommand
.It LocalCommand
.It LocalForward
.It LogLevel
@@ -530,13 +555,14 @@ For full details of the options listed below, and their possible values, see
.It NumberOfPasswordPrompts
.It PasswordAuthentication
.It PermitLocalCommand
+.It PermitRemoteOpen
.It PKCS11Provider
.It Port
.It PreferredAuthentications
.It ProxyCommand
.It ProxyJump
.It ProxyUseFdpass
-.It PubkeyAcceptedKeyTypes
+.It PubkeyAcceptedAlgorithms
.It PubkeyAuthentication
.It RekeyLimit
.It RemoteCommand
@@ -545,7 +571,9 @@ For full details of the options listed below, and their possible values, see
.It SendEnv
.It ServerAliveInterval
.It ServerAliveCountMax
+.It SessionType
.It SetEnv
+.It StdinNull
.It StreamLocalBindMask
.It StreamLocalBindUnlink
.It StrictHostKeyChecking
@@ -566,10 +594,7 @@ This can be specified on a
per-host basis in the configuration file.
.Pp
.It Fl Q Ar query_option
-Queries
-.Nm
-for the algorithms supported for the specified version 2.
-The available features are:
+Queries for the algorithms supported by one of the following features:
.Ar cipher
(supported symmetric ciphers),
.Ar cipher-auth
@@ -702,6 +727,11 @@ Subsystems facilitate the use of SSH
as a secure transport for other applications (e.g.\&
.Xr sftp 1 ) .
The subsystem is specified as the remote command.
+Refer to the description of
+.Cm SessionType
+in
+.Xr ssh_config 5
+for details.
.Pp
.It Fl T
Disable pseudo-terminal allocation.
@@ -831,7 +861,7 @@ The methods available for authentication are:
GSSAPI-based authentication,
host-based authentication,
public key authentication,
-challenge-response authentication,
+keyboard-interactive authentication,
and password authentication.
Authentication methods are tried in the order specified above,
though
@@ -906,7 +936,7 @@ or higher (e.g. by using the
.Fl v
flag).
.Pp
-The user creates his/her key pair by running
+The user creates their key pair by running
.Xr ssh-keygen 1 .
This stores the private key in
.Pa ~/.ssh/id_dsa
@@ -940,7 +970,7 @@ in the user's home directory.
The user should then copy the public key
to
.Pa ~/.ssh/authorized_keys
-in his/her home directory on the remote machine.
+in their home directory on the remote machine.
The
.Pa authorized_keys
file corresponds to the conventional
@@ -969,11 +999,11 @@ directive in
.Xr ssh_config 5
for more information.
.Pp
-Challenge-response authentication works as follows:
+Keyboard-interactive authentication works as follows:
The server sends an arbitrary
.Qq challenge
-text, and prompts for a response.
-Examples of challenge-response authentication include
+text and prompts for a response, possibly multiple times.
+Examples of keyboard-interactive authentication include
.Bx
Authentication (see
.Xr login.conf 5 )
@@ -1409,6 +1439,25 @@ or related script.
may be necessary to redirect the input from
.Pa /dev/null
to make this work.)
+.It Ev SSH_ASKPASS_REQUIRE
+Allows further control over the use of an askpass program.
+If this variable is set to
+.Dq never
+then
+.Nm
+will never attempt to use one.
+If it is set to
+.Dq prefer ,
+then
+.Nm
+will prefer to use the askpass program instead of the TTY when requesting
+passwords.
+Finally, if the variable is set to
+.Dq force ,
+then the askpass program will be used for all passphrase input regardless
+of whether
+.Ev DISPLAY
+is set.
.It Ev SSH_AUTH_SOCK
Identifies the path of a
.Ux Ns -domain
diff --git a/ssh.c b/ssh.c
index 98b6ce788..e6fe80909 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.527 2020/04/10 00:52:07 dtucker Exp $ */
+/* $OpenBSD: ssh.c,v 1.569 2021/09/20 04:02:13 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -16,7 +16,7 @@
* Copyright (c) 1999 Niels Provos. All rights reserved.
* Copyright (c) 2000, 2001, 2002, 2003 Markus Friedl. All rights reserved.
*
- * Modified to work with SSL by Niels Provos <provos@citi.umich.edu>
+ * Modified to work with SSLeay by Niels Provos <provos@citi.umich.edu>
* in Canada (German citizen).
*
* Redistribution and use in source and binary forms, with or without
@@ -126,30 +126,14 @@ int debug_flag = 0;
/* Flag indicating whether a tty should be requested */
int tty_flag = 0;
-/* don't exec a shell */
-int no_shell_flag = 0;
-
-/*
- * Flag indicating that nothing should be read from stdin. This can be set
- * on the command line.
- */
-int stdin_null_flag = 0;
-
/*
* Flag indicating that the current process should be backgrounded and
- * a new slave launched in the foreground for ControlPersist.
+ * a new mux-client launched in the foreground for ControlPersist.
*/
int need_controlpersist_detach = 0;
-/* Copies of flags for ControlPersist foreground slave */
-int ostdin_null_flag, ono_shell_flag, otty_flag, orequest_tty;
-
-/*
- * Flag indicating that ssh should fork after authentication. This is useful
- * so that the passphrase can be entered manually, and then ssh goes to the
- * background.
- */
-int fork_after_authentication_flag = 0;
+/* Copies of flags for ControlPersist foreground mux-client */
+int ostdin_null_flag, osession_type, otty_flag, orequest_tty;
/*
* General data structure for command line options and options configurable
@@ -173,10 +157,6 @@ char *host;
*/
char *forward_agent_sock_path = NULL;
-/* Various strings used to to percent_expand() arguments */
-static char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
-static char uidstr[32], *host_arg, *conn_hash_hex;
-
/* socket address the host resolves to */
struct sockaddr_storage hostaddr;
@@ -186,9 +166,6 @@ Sensitive sensitive_data;
/* command to be executed */
struct sshbuf *command;
-/* Should we execute a command or invoke a subsystem? */
-int subsystem_flag = 0;
-
/* # of replies received for global requests */
static int forward_confirms_pending = -1;
@@ -208,13 +185,13 @@ usage(void)
" [-i identity_file] [-J [user@]host[:port]] [-L address]\n"
" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
" [-Q query_option] [-R address] [-S ctl_path] [-W host:port]\n"
-" [-w local_tun[:remote_tun]] destination [command]\n"
+" [-w local_tun[:remote_tun]] destination [command [argument ...]]\n"
);
exit(255);
}
-static int ssh_session2(struct ssh *, struct passwd *);
-static void load_public_identity_files(struct passwd *);
+static int ssh_session2(struct ssh *, const struct ssh_conn_info *);
+static void load_public_identity_files(const struct ssh_conn_info *);
static void main_sigchld_handler(int);
/* ~/ expand a list of paths. NB. assumes path[n] is heap-allocated. */
@@ -231,35 +208,40 @@ tilde_expand_paths(char **paths, u_int num_paths)
}
}
-#define DEFAULT_CLIENT_PERCENT_EXPAND_ARGS \
- "C", conn_hash_hex, \
- "L", shorthost, \
- "i", uidstr, \
- "l", thishost, \
- "n", host_arg, \
- "p", portstr
-
/*
* Expands the set of percent_expand options used by the majority of keywords
* in the client that support percent expansion.
* Caller must free returned string.
*/
static char *
-default_client_percent_expand(const char *str, const char *homedir,
- const char *remhost, const char *remuser, const char *locuser)
+default_client_percent_expand(const char *str,
+ const struct ssh_conn_info *cinfo)
{
return percent_expand(str,
- /* values from statics above */
- DEFAULT_CLIENT_PERCENT_EXPAND_ARGS,
- /* values from arguments */
- "d", homedir,
- "h", remhost,
- "r", remuser,
- "u", locuser,
+ DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(cinfo),
(char *)NULL);
}
/*
+ * Expands the set of percent_expand options used by the majority of keywords
+ * AND perform environment variable substitution.
+ * Caller must free returned string.
+ */
+static char *
+default_client_percent_dollar_expand(const char *str,
+ const struct ssh_conn_info *cinfo)
+{
+ char *ret;
+
+ ret = percent_dollar_expand(str,
+ DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(cinfo),
+ (char *)NULL);
+ if (ret == NULL)
+ fatal("invalid environment variable expansion");
+ return ret;
+}
+
+/*
* Attempt to resolve a host name / port to a set of addresses and
* optionally return any CNAMEs encountered along the way.
* Returns NULL on failure.
@@ -277,6 +259,7 @@ resolve_host(const char *name, int port, int logerr, char *cname, size_t clen)
port = default_ssh_port();
if (cname != NULL)
*cname = '\0';
+ debug3_f("lookup %s:%d", name, port);
snprintf(strport, sizeof strport, "%d", port);
memset(&hints, 0, sizeof(hints));
@@ -294,8 +277,8 @@ resolve_host(const char *name, int port, int logerr, char *cname, size_t clen)
}
if (cname != NULL && res->ai_canonname != NULL) {
if (strlcpy(cname, res->ai_canonname, clen) >= clen) {
- error("%s: host \"%s\" cname \"%s\" too long (max %lu)",
- __func__, name, res->ai_canonname, (u_long)clen);
+ error_f("host \"%s\" cname \"%s\" too long (max %lu)",
+ name, res->ai_canonname, (u_long)clen);
if (clen > 0)
*cname = '\0';
}
@@ -359,29 +342,27 @@ resolve_addr(const char *name, int port, char *caddr, size_t clen)
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_NUMERICHOST|AI_NUMERICSERV;
if ((gaierr = getaddrinfo(name, strport, &hints, &res)) != 0) {
- debug2("%s: could not resolve name %.100s as address: %s",
- __func__, name, ssh_gai_strerror(gaierr));
+ debug2_f("could not resolve name %.100s as address: %s",
+ name, ssh_gai_strerror(gaierr));
return NULL;
}
if (res == NULL) {
- debug("%s: getaddrinfo %.100s returned no addresses",
- __func__, name);
+ debug_f("getaddrinfo %.100s returned no addresses", name);
return NULL;
}
if (res->ai_next != NULL) {
- debug("%s: getaddrinfo %.100s returned multiple addresses",
- __func__, name);
+ debug_f("getaddrinfo %.100s returned multiple addresses", name);
goto fail;
}
if ((gaierr = getnameinfo(res->ai_addr, res->ai_addrlen,
addr, sizeof(addr), NULL, 0, NI_NUMERICHOST)) != 0) {
- debug("%s: Could not format address for name %.100s: %s",
- __func__, name, ssh_gai_strerror(gaierr));
+ debug_f("Could not format address for name %.100s: %s",
+ name, ssh_gai_strerror(gaierr));
goto fail;
}
if (strlcpy(caddr, addr, clen) >= clen) {
- error("%s: host \"%s\" addr \"%s\" too long (max %lu)",
- __func__, name, addr, (u_long)clen);
+ error_f("host \"%s\" addr \"%s\" too long (max %lu)",
+ name, addr, (u_long)clen);
if (clen > 0)
*caddr = '\0';
fail:
@@ -402,7 +383,7 @@ check_follow_cname(int direct, char **namep, const char *cname)
int i;
struct allowed_cname *rule;
- if (*cname == '\0' || options.num_permitted_cnames == 0 ||
+ if (*cname == '\0' || !config_has_permitted_cnames(&options) ||
strcmp(*namep, cname) == 0)
return 0;
if (options.canonicalize_hostname == SSH_CANONICALISE_NO)
@@ -414,7 +395,7 @@ check_follow_cname(int direct, char **namep, const char *cname)
if (!direct &&
options.canonicalize_hostname != SSH_CANONICALISE_ALWAYS)
return 0;
- debug3("%s: check \"%s\" CNAME \"%s\"", __func__, *namep, cname);
+ debug3_f("check \"%s\" CNAME \"%s\"", *namep, cname);
for (i = 0; i < options.num_permitted_cnames; i++) {
rule = options.permitted_cnames + i;
if (match_pattern_list(*namep, rule->source_list, 1) != 1 ||
@@ -448,10 +429,10 @@ resolve_canonicalize(char **hostp, int port)
*/
if ((addrs = resolve_addr(*hostp, port,
newname, sizeof(newname))) != NULL) {
- debug2("%s: hostname %.100s is address", __func__, *hostp);
+ debug2_f("hostname %.100s is address", *hostp);
if (strcasecmp(*hostp, newname) != 0) {
- debug2("%s: canonicalised address \"%s\" => \"%s\"",
- __func__, *hostp, newname);
+ debug2_f("canonicalised address \"%s\" => \"%s\"",
+ *hostp, newname);
free(*hostp);
*hostp = xstrdup(newname);
}
@@ -464,8 +445,7 @@ resolve_canonicalize(char **hostp, int port)
* attempts at canonicalisation.
*/
if (is_addr_fast(*hostp)) {
- debug("%s: hostname %.100s is an unrecognised address",
- __func__, *hostp);
+ debug_f("hostname %.100s is an unrecognised address", *hostp);
return NULL;
}
@@ -484,7 +464,7 @@ resolve_canonicalize(char **hostp, int port)
/* If domain name is anchored, then resolve it now */
if ((*hostp)[strlen(*hostp) - 1] == '.') {
- debug3("%s: name is fully qualified", __func__);
+ debug3_f("name is fully qualified");
fullhost = xstrdup(*hostp);
if ((addrs = resolve_host(fullhost, port, 0,
newname, sizeof(newname))) != NULL)
@@ -500,16 +480,17 @@ resolve_canonicalize(char **hostp, int port)
ndots++;
}
if (ndots > options.canonicalize_max_dots) {
- debug3("%s: not canonicalizing hostname \"%s\" (max dots %d)",
- __func__, *hostp, options.canonicalize_max_dots);
+ debug3_f("not canonicalizing hostname \"%s\" (max dots %d)",
+ *hostp, options.canonicalize_max_dots);
return NULL;
}
/* Attempt each supplied suffix */
for (i = 0; i < options.num_canonical_domains; i++) {
+ if (strcasecmp(options.canonical_domains[i], "none") == 0)
+ break;
xasprintf(&fullhost, "%s.%s.", *hostp,
options.canonical_domains[i]);
- debug3("%s: attempting \"%s\" => \"%s\"", __func__,
- *hostp, fullhost);
+ debug3_f("attempting \"%s\" => \"%s\"", *hostp, fullhost);
if ((addrs = resolve_host(fullhost, port, 0,
newname, sizeof(newname))) == NULL) {
free(fullhost);
@@ -530,7 +511,7 @@ resolve_canonicalize(char **hostp, int port)
notfound:
if (!options.canonicalize_fallback_local)
fatal("%s: Could not resolve host \"%s\"", __progname, *hostp);
- debug2("%s: host %s not found in any suffix", __func__, *hostp);
+ debug2_f("host %s not found in any suffix", *hostp);
return NULL;
}
@@ -546,14 +527,14 @@ check_load(int r, const char *path, const char *message)
break;
case SSH_ERR_INTERNAL_ERROR:
case SSH_ERR_ALLOC_FAIL:
- fatal("load %s \"%s\": %s", message, path, ssh_err(r));
+ fatal_r(r, "load %s \"%s\"", message, path);
case SSH_ERR_SYSTEM_ERROR:
/* Ignore missing files */
if (errno == ENOENT)
break;
/* FALLTHROUGH */
default:
- error("load %s \"%s\": %s", message, path, ssh_err(r));
+ error_r(r, "load %s \"%s\"", message, path);
break;
}
}
@@ -611,6 +592,25 @@ set_addrinfo_port(struct addrinfo *addrs, int port)
}
}
+static void
+ssh_conn_info_free(struct ssh_conn_info *cinfo)
+{
+ if (cinfo == NULL)
+ return;
+ free(cinfo->conn_hash_hex);
+ free(cinfo->shorthost);
+ free(cinfo->uidstr);
+ free(cinfo->keyalias);
+ free(cinfo->thishost);
+ free(cinfo->host_arg);
+ free(cinfo->portstr);
+ free(cinfo->remhost);
+ free(cinfo->remuser);
+ free(cinfo->homedir);
+ free(cinfo->locuser);
+ free(cinfo);
+}
+
/*
* Main program for the ssh client.
*/
@@ -620,8 +620,8 @@ main(int ac, char **av)
struct ssh *ssh = NULL;
int i, r, opt, exit_status, use_syslog, direct, timeout_ms;
int was_addr, config_test = 0, opt_terminated = 0, want_final_pass = 0;
- char *p, *cp, *line, *argv0, buf[PATH_MAX], *logfile;
- char cname[NI_MAXHOST];
+ char *p, *cp, *line, *argv0, *logfile, *host_arg;
+ char cname[NI_MAXHOST], thishost[NI_MAXHOST];
struct stat st;
struct passwd *pw;
extern int optind, optreset;
@@ -629,10 +629,18 @@ main(int ac, char **av)
struct Forward fwd;
struct addrinfo *addrs = NULL;
size_t n, len;
+ u_int j;
+ struct ssh_conn_info *cinfo = NULL;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd();
+ /*
+ * Discard other fds that are hanging around. These can cause problem
+ * with backgrounded ssh processes started by ControlPersist.
+ */
+ closefrom(STDERR_FILENO + 1);
+
__progname = ssh_get_progname(av[0]);
#ifndef HAVE_SETPROCTITLE
@@ -648,12 +656,6 @@ main(int ac, char **av)
seed_rng();
- /*
- * Discard other fds that are hanging around. These can cause problem
- * with backgrounded ssh processes started by ControlPersist.
- */
- closefrom(STDERR_FILENO + 1);
-
/* Get user data. */
pw = getpwuid(getuid());
if (!pw) {
@@ -709,11 +711,11 @@ main(int ac, char **av)
options.address_family = AF_INET6;
break;
case 'n':
- stdin_null_flag = 1;
+ options.stdin_null = 1;
break;
case 'f':
- fork_after_authentication_flag = 1;
- stdin_null_flag = 1;
+ options.fork_after_authentication = 1;
+ options.stdin_null = 1;
break;
case 'x':
options.forward_x11 = 0;
@@ -780,10 +782,12 @@ main(int ac, char **av)
else if (strcmp(optarg, "key-plain") == 0)
cp = sshkey_alg_list(0, 1, 0, '\n');
else if (strcmp(optarg, "key-sig") == 0 ||
- strcasecmp(optarg, "PubkeyAcceptedKeyTypes") == 0 ||
+ strcasecmp(optarg, "PubkeyAcceptedKeyTypes") == 0 || /* deprecated name */
+ strcasecmp(optarg, "PubkeyAcceptedAlgorithms") == 0 ||
strcasecmp(optarg, "HostKeyAlgorithms") == 0 ||
- strcasecmp(optarg, "HostbasedKeyTypes") == 0 ||
- strcasecmp(optarg, "HostbasedAcceptedKeyTypes") == 0)
+ strcasecmp(optarg, "HostbasedKeyTypes") == 0 || /* deprecated name */
+ strcasecmp(optarg, "HostbasedAcceptedKeyTypes") == 0 || /* deprecated name */
+ strcasecmp(optarg, "HostbasedAcceptedAlgorithms") == 0)
cp = sshkey_alg_list(0, 0, 1, '\n');
else if (strcmp(optarg, "sig") == 0)
cp = sshkey_alg_list(0, 1, 1, '\n');
@@ -869,13 +873,7 @@ main(int ac, char **av)
break;
case 'V':
fprintf(stderr, "%s, %s\n",
- SSH_RELEASE,
-#ifdef WITH_OPENSSL
- OpenSSL_version(OPENSSL_VERSION)
-#else
- "without OpenSSL"
-#endif
- );
+ SSH_RELEASE, SSH_OPENSSL_VERSION);
if (opt == 'V')
exit(0);
break;
@@ -905,7 +903,7 @@ main(int ac, char **av)
exit(255);
}
options.request_tty = REQUEST_TTY_NO;
- no_shell_flag = 1;
+ options.session_type = SESSION_TYPE_NONE;
break;
case 'q':
options.log_level = SYSLOG_LEVEL_QUIET;
@@ -1008,7 +1006,10 @@ main(int ac, char **av)
#endif
break;
case 'N':
- no_shell_flag = 1;
+ if (options.session_type != -1 &&
+ options.session_type != SESSION_TYPE_NONE)
+ fatal("Cannot specify -N with -s/SessionType");
+ options.session_type = SESSION_TYPE_NONE;
options.request_tty = REQUEST_TTY_NO;
break;
case 'T':
@@ -1023,7 +1024,10 @@ main(int ac, char **av)
free(line);
break;
case 's':
- subsystem_flag = 1;
+ if (options.session_type != -1 &&
+ options.session_type != SESSION_TYPE_SUBSYSTEM)
+ fatal("Cannot specify -s with -N/SessionType");
+ options.session_type = SESSION_TYPE_SUBSYSTEM;
break;
case 'S':
free(options.control_path);
@@ -1106,7 +1110,7 @@ main(int ac, char **av)
*/
if (!ac) {
/* No command specified - execute shell on a tty. */
- if (subsystem_flag) {
+ if (options.session_type == SESSION_TYPE_SUBSYSTEM) {
fprintf(stderr,
"You must specify a subsystem to invoke.\n");
usage();
@@ -1116,8 +1120,7 @@ main(int ac, char **av)
for (i = 0; i < ac; i++) {
if ((r = sshbuf_putf(command, "%s%s",
i ? " " : "", av[i])) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "buffer error");
}
}
@@ -1137,13 +1140,7 @@ main(int ac, char **av)
!use_syslog);
if (debug_flag)
- logit("%s, %s", SSH_RELEASE,
-#ifdef WITH_OPENSSL
- OpenSSL_version(OPENSSL_VERSION)
-#else
- "without OpenSSL"
-#endif
- );
+ logit("%s, %s", SSH_RELEASE, SSH_OPENSSL_VERSION);
/* Parse the configuration files */
process_config_files(host_arg, pw, 0, &want_final_pass);
@@ -1190,7 +1187,7 @@ main(int ac, char **av)
*/
direct = option_clear_or_none(options.proxy_command) &&
options.jump_host == NULL;
- if (addrs == NULL && options.num_permitted_cnames != 0 && (direct ||
+ if (addrs == NULL && config_has_permitted_cnames(&options) && (direct ||
options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) {
if ((addrs = resolve_host(host, options.port,
direct, cname, sizeof(cname))) == NULL) {
@@ -1226,21 +1223,28 @@ main(int ac, char **av)
}
/* Fill configuration defaults. */
- fill_default_options(&options);
+ if (fill_default_options(&options) != 0)
+ cleanup_exit(255);
+
+ if (options.user == NULL)
+ options.user = xstrdup(pw->pw_name);
/*
* If ProxyJump option specified, then construct a ProxyCommand now.
*/
if (options.jump_host != NULL) {
char port_s[8];
- const char *sshbin = argv0;
+ const char *jumpuser = options.jump_user, *sshbin = argv0;
int port = options.port, jumpport = options.jump_port;
if (port <= 0)
port = default_ssh_port();
if (jumpport <= 0)
jumpport = default_ssh_port();
- if (strcmp(options.jump_host, host) == 0 && port == jumpport)
+ if (jumpuser == NULL)
+ jumpuser = options.user;
+ if (strcmp(options.jump_host, host) == 0 && port == jumpport &&
+ strcmp(options.user, jumpuser) == 0)
fatal("jumphost loop via %s", options.jump_host);
/*
@@ -1314,13 +1318,19 @@ main(int ac, char **av)
fatal("Cannot execute command-line and remote command.");
/* Cannot fork to background if no command. */
- if (fork_after_authentication_flag && sshbuf_len(command) == 0 &&
- options.remote_command == NULL && !no_shell_flag)
+ if (options.fork_after_authentication && sshbuf_len(command) == 0 &&
+ options.remote_command == NULL &&
+ options.session_type != SESSION_TYPE_NONE)
fatal("Cannot fork into background without a command "
"to execute.");
/* reinit */
log_init(argv0, options.log_level, options.log_facility, !use_syslog);
+ for (j = 0; j < options.num_log_verbose; j++) {
+ if (strcasecmp(options.log_verbose[j], "none") == 0)
+ break;
+ log_verbose_add(options.log_verbose[j]);
+ }
if (options.request_tty == REQUEST_TTY_YES ||
options.request_tty == REQUEST_TTY_FORCE)
@@ -1335,7 +1345,7 @@ main(int ac, char **av)
(muxclient_command && muxclient_command != SSHMUX_COMMAND_PROXY))
tty_flag = 0;
/* Do not allocate a tty if stdin is not a tty. */
- if ((!isatty(fileno(stdin)) || stdin_null_flag) &&
+ if ((!isatty(fileno(stdin)) || options.stdin_null) &&
options.request_tty != REQUEST_TTY_FORCE) {
if (tty_flag)
logit("Pseudo-terminal will not be allocated because "
@@ -1343,20 +1353,25 @@ main(int ac, char **av)
tty_flag = 0;
}
- if (options.user == NULL)
- options.user = xstrdup(pw->pw_name);
-
/* Set up strings used to percent_expand() arguments */
+ cinfo = xcalloc(1, sizeof(*cinfo));
if (gethostname(thishost, sizeof(thishost)) == -1)
fatal("gethostname: %s", strerror(errno));
- strlcpy(shorthost, thishost, sizeof(shorthost));
- shorthost[strcspn(thishost, ".")] = '\0';
- snprintf(portstr, sizeof(portstr), "%d", options.port);
- snprintf(uidstr, sizeof(uidstr), "%llu",
+ cinfo->thishost = xstrdup(thishost);
+ thishost[strcspn(thishost, ".")] = '\0';
+ cinfo->shorthost = xstrdup(thishost);
+ xasprintf(&cinfo->portstr, "%d", options.port);
+ xasprintf(&cinfo->uidstr, "%llu",
(unsigned long long)pw->pw_uid);
-
- conn_hash_hex = ssh_connection_hash(thishost, host, portstr,
- options.user);
+ cinfo->keyalias = xstrdup(options.host_key_alias ?
+ options.host_key_alias : host_arg);
+ cinfo->conn_hash_hex = ssh_connection_hash(cinfo->thishost, host,
+ cinfo->portstr, options.user);
+ cinfo->host_arg = xstrdup(host_arg);
+ cinfo->remhost = xstrdup(host);
+ cinfo->remuser = xstrdup(options.user);
+ cinfo->homedir = xstrdup(pw->pw_dir);
+ cinfo->locuser = xstrdup(pw->pw_name);
/*
* Expand tokens in arguments. NB. LocalCommand is expanded later,
@@ -1367,26 +1382,25 @@ main(int ac, char **av)
debug3("expanding RemoteCommand: %s", options.remote_command);
cp = options.remote_command;
options.remote_command = default_client_percent_expand(cp,
- pw->pw_dir, host, options.user, pw->pw_name);
+ cinfo);
debug3("expanded RemoteCommand: %s", options.remote_command);
free(cp);
if ((r = sshbuf_put(command, options.remote_command,
strlen(options.remote_command))) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "buffer error");
}
if (options.control_path != NULL) {
cp = tilde_expand_filename(options.control_path, getuid());
free(options.control_path);
- options.control_path = default_client_percent_expand(cp,
- pw->pw_dir, host, options.user, pw->pw_name);
+ options.control_path = default_client_percent_dollar_expand(cp,
+ cinfo);
free(cp);
}
if (options.identity_agent != NULL) {
p = tilde_expand_filename(options.identity_agent, getuid());
- cp = default_client_percent_expand(p,
- pw->pw_dir, host, options.user, pw->pw_name);
+ cp = default_client_percent_dollar_expand(p, cinfo);
free(p);
free(options.identity_agent);
options.identity_agent = cp;
@@ -1395,19 +1409,55 @@ main(int ac, char **av)
if (options.forward_agent_sock_path != NULL) {
p = tilde_expand_filename(options.forward_agent_sock_path,
getuid());
- cp = default_client_percent_expand(p,
- pw->pw_dir, host, options.user, pw->pw_name);
+ cp = default_client_percent_dollar_expand(p, cinfo);
free(p);
free(options.forward_agent_sock_path);
options.forward_agent_sock_path = cp;
+ if (stat(options.forward_agent_sock_path, &st) != 0) {
+ error("Cannot forward agent socket path \"%s\": %s",
+ options.forward_agent_sock_path, strerror(errno));
+ if (options.exit_on_forward_failure)
+ cleanup_exit(255);
+ }
+ }
+
+ if (options.num_system_hostfiles > 0 &&
+ strcasecmp(options.system_hostfiles[0], "none") == 0) {
+ if (options.num_system_hostfiles > 1)
+ fatal("Invalid GlobalKnownHostsFiles: \"none\" "
+ "appears with other entries");
+ free(options.system_hostfiles[0]);
+ options.system_hostfiles[0] = NULL;
+ options.num_system_hostfiles = 0;
+ }
+
+ if (options.num_user_hostfiles > 0 &&
+ strcasecmp(options.user_hostfiles[0], "none") == 0) {
+ if (options.num_user_hostfiles > 1)
+ fatal("Invalid UserKnownHostsFiles: \"none\" "
+ "appears with other entries");
+ free(options.user_hostfiles[0]);
+ options.user_hostfiles[0] = NULL;
+ options.num_user_hostfiles = 0;
+ }
+ for (j = 0; j < options.num_user_hostfiles; j++) {
+ if (options.user_hostfiles[j] == NULL)
+ continue;
+ cp = tilde_expand_filename(options.user_hostfiles[j], getuid());
+ p = default_client_percent_dollar_expand(cp, cinfo);
+ if (strcmp(options.user_hostfiles[j], p) != 0)
+ debug3("expanded UserKnownHostsFile '%s' -> "
+ "'%s'", options.user_hostfiles[j], p);
+ free(options.user_hostfiles[j]);
+ free(cp);
+ options.user_hostfiles[j] = p;
}
for (i = 0; i < options.num_local_forwards; i++) {
if (options.local_forwards[i].listen_path != NULL) {
cp = options.local_forwards[i].listen_path;
p = options.local_forwards[i].listen_path =
- default_client_percent_expand(cp,
- pw->pw_dir, host, options.user, pw->pw_name);
+ default_client_percent_expand(cp, cinfo);
if (strcmp(cp, p) != 0)
debug3("expanded LocalForward listen path "
"'%s' -> '%s'", cp, p);
@@ -1416,8 +1466,7 @@ main(int ac, char **av)
if (options.local_forwards[i].connect_path != NULL) {
cp = options.local_forwards[i].connect_path;
p = options.local_forwards[i].connect_path =
- default_client_percent_expand(cp,
- pw->pw_dir, host, options.user, pw->pw_name);
+ default_client_percent_expand(cp, cinfo);
if (strcmp(cp, p) != 0)
debug3("expanded LocalForward connect path "
"'%s' -> '%s'", cp, p);
@@ -1429,8 +1478,7 @@ main(int ac, char **av)
if (options.remote_forwards[i].listen_path != NULL) {
cp = options.remote_forwards[i].listen_path;
p = options.remote_forwards[i].listen_path =
- default_client_percent_expand(cp,
- pw->pw_dir, host, options.user, pw->pw_name);
+ default_client_percent_expand(cp, cinfo);
if (strcmp(cp, p) != 0)
debug3("expanded RemoteForward listen path "
"'%s' -> '%s'", cp, p);
@@ -1439,8 +1487,7 @@ main(int ac, char **av)
if (options.remote_forwards[i].connect_path != NULL) {
cp = options.remote_forwards[i].connect_path;
p = options.remote_forwards[i].connect_path =
- default_client_percent_expand(cp,
- pw->pw_dir, host, options.user, pw->pw_name);
+ default_client_percent_expand(cp, cinfo);
if (strcmp(cp, p) != 0)
debug3("expanded RemoteForward connect path "
"'%s' -> '%s'", cp, p);
@@ -1491,13 +1538,16 @@ main(int ac, char **av)
cleanup_exit(255); /* resolve_host logs the error */
}
- timeout_ms = options.connection_timeout * 1000;
+ if (options.connection_timeout >= INT_MAX/1000)
+ timeout_ms = INT_MAX;
+ else
+ timeout_ms = options.connection_timeout * 1000;
/* Open a connection to the remote host. */
if (ssh_connect(ssh, host, host_arg, addrs, &hostaddr, options.port,
- options.address_family, options.connection_attempts,
+ options.connection_attempts,
&timeout_ms, options.tcp_keep_alive) != 0)
- exit(255);
+ exit(255);
if (addrs != NULL)
freeaddrinfo(addrs);
@@ -1523,13 +1573,13 @@ main(int ac, char **av)
/* XXX check errors? */
#define L_PUBKEY(p,o) do { \
if ((o) >= sensitive_data.nkeys) \
- fatal("%s pubkey out of array bounds", __func__); \
+ fatal_f("pubkey out of array bounds"); \
check_load(sshkey_load_public(p, &(sensitive_data.keys[o]), NULL), \
p, "pubkey"); \
} while (0)
#define L_CERT(p,o) do { \
if ((o) >= sensitive_data.nkeys) \
- fatal("%s cert out of array bounds", __func__); \
+ fatal_f("cert out of array bounds"); \
check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), p, "cert"); \
} while (0)
@@ -1547,24 +1597,8 @@ main(int ac, char **av)
}
}
- /* Create ~/.ssh * directory if it doesn't already exist. */
- if (config == NULL) {
- r = snprintf(buf, sizeof buf, "%s%s%s", pw->pw_dir,
- strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR);
- if (r > 0 && (size_t)r < sizeof(buf) && stat(buf, &st) == -1) {
-#ifdef WITH_SELINUX
- ssh_selinux_setfscreatecon(buf);
-#endif
- if (mkdir(buf, 0700) < 0)
- error("Could not create directory '%.200s'.",
- buf);
-#ifdef WITH_SELINUX
- ssh_selinux_setfscreatecon(NULL);
-#endif
- }
- }
/* load options.identity_files */
- load_public_identity_files(pw);
+ load_public_identity_files(cinfo);
/* optionally set the SSH_AUTHSOCKET_ENV_NAME variable */
if (options.identity_agent &&
@@ -1573,7 +1607,8 @@ main(int ac, char **av)
unsetenv(SSH_AUTHSOCKET_ENV_NAME);
} else {
cp = options.identity_agent;
- if (cp[0] == '$') {
+ /* legacy (limited) format */
+ if (cp[0] == '$' && cp[1] != '{') {
if (!valid_env_name(cp + 1)) {
fatal("Invalid IdentityAgent "
"environment variable name %s", cp);
@@ -1596,7 +1631,7 @@ main(int ac, char **av)
fatal("Invalid ForwardAgent environment variable name %s", cp);
}
if ((p = getenv(cp + 1)) != NULL)
- forward_agent_sock_path = p;
+ forward_agent_sock_path = xstrdup(p);
else
options.forward_agent = 0;
free(cp);
@@ -1615,14 +1650,7 @@ main(int ac, char **av)
/* Log into the remote system. Never returns if the login fails. */
ssh_login(ssh, &sensitive_data, host, (struct sockaddr *)&hostaddr,
- options.port, pw, timeout_ms);
-
- if (ssh_packet_connection_is_on_socket(ssh)) {
- verbose("Authenticated to %s ([%s]:%d).", host,
- ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
- } else {
- verbose("Authenticated to %s (via proxy).", host);
- }
+ options.port, pw, timeout_ms, cinfo);
/* We no longer need the private host keys. Clear them now. */
if (sensitive_data.nkeys != 0) {
@@ -1649,8 +1677,13 @@ main(int ac, char **av)
options.certificate_files[i] = NULL;
}
+#ifdef ENABLE_PKCS11
+ (void)pkcs11_del_provider(options.pkcs11_provider);
+#endif
+
skip_connect:
- exit_status = ssh_session2(ssh, pw);
+ exit_status = ssh_session2(ssh, cinfo);
+ ssh_conn_info_free(cinfo);
ssh_packet_close(ssh);
if (options.control_path != NULL && muxserver_sock != -1)
@@ -1666,9 +1699,8 @@ static void
control_persist_detach(void)
{
pid_t pid;
- int devnull, keep_stderr;
- debug("%s: backgrounding master process", __func__);
+ debug_f("backgrounding master process");
/*
* master (current process) into the background, and make the
@@ -1676,16 +1708,17 @@ control_persist_detach(void)
*/
switch ((pid = fork())) {
case -1:
- fatal("%s: fork: %s", __func__, strerror(errno));
+ fatal_f("fork: %s", strerror(errno));
case 0:
/* Child: master process continues mainloop */
break;
default:
- /* Parent: set up mux slave to connect to backgrounded master */
- debug2("%s: background process is %ld", __func__, (long)pid);
- stdin_null_flag = ostdin_null_flag;
+ /* Parent: set up mux client to connect to backgrounded master */
+ debug2_f("background process is %ld", (long)pid);
+ options.stdin_null = ostdin_null_flag;
options.request_tty = orequest_tty;
tty_flag = otty_flag;
+ options.session_type = osession_type;
close(muxserver_sock);
muxserver_sock = -1;
options.control_master = SSHCTL_MASTER_NO;
@@ -1693,18 +1726,8 @@ control_persist_detach(void)
/* muxclient() doesn't return on success. */
fatal("Failed to connect to new control master");
}
- if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
- error("%s: open(\"/dev/null\"): %s", __func__,
- strerror(errno));
- } else {
- keep_stderr = log_is_on_stderr() && debug_flag;
- if (dup2(devnull, STDIN_FILENO) == -1 ||
- dup2(devnull, STDOUT_FILENO) == -1 ||
- (!keep_stderr && dup2(devnull, STDERR_FILENO) == -1))
- error("%s: dup2: %s", __func__, strerror(errno));
- if (devnull > STDERR_FILENO)
- close(devnull);
- }
+ if (stdfd_devnull(1, 1, !(log_is_on_stderr() && debug_flag)) == -1)
+ error_f("stdfd_devnull failed");
daemon(1, 1);
setproctitle("%s [mux]", options.control_path);
}
@@ -1716,9 +1739,11 @@ fork_postauth(void)
if (need_controlpersist_detach)
control_persist_detach();
debug("forking to background");
- fork_after_authentication_flag = 0;
+ options.fork_after_authentication = 0;
if (daemon(1, 1) == -1)
fatal("daemon() failed: %.200s", strerror(errno));
+ if (stdfd_devnull(1, 1, !(log_is_on_stderr() && debug_flag)) == -1)
+ error_f("stdfd_devnull failed");
}
static void
@@ -1727,12 +1752,12 @@ forwarding_success(void)
if (forward_confirms_pending == -1)
return;
if (--forward_confirms_pending == 0) {
- debug("%s: all expected forwarding replies received", __func__);
- if (fork_after_authentication_flag)
+ debug_f("all expected forwarding replies received");
+ if (options.fork_after_authentication)
fork_postauth();
} else {
- debug2("%s: %d expected forwarding replies remaining",
- __func__, forward_confirms_pending);
+ debug2_f("%d expected forwarding replies remaining",
+ forward_confirms_pending);
}
}
@@ -1755,7 +1780,7 @@ ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
if (rfwd->listen_path == NULL && rfwd->listen_port == 0) {
if (type == SSH2_MSG_REQUEST_SUCCESS) {
if ((r = sshpkt_get_u32(ssh, &port)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse packet");
if (port > 65535) {
error("Invalid allocated port %u for remote "
"forward to %s:%d", port,
@@ -1768,7 +1793,8 @@ ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
rfwd->allocated_port = (int)port;
logit("Allocated port %u for remote "
"forward to %s:%d",
- rfwd->allocated_port, rfwd->connect_host,
+ rfwd->allocated_port, rfwd->connect_path ?
+ rfwd->connect_path : rfwd->connect_host,
rfwd->connect_port);
channel_update_permission(ssh,
rfwd->handle, rfwd->allocated_port);
@@ -1821,7 +1847,7 @@ ssh_tun_confirm(struct ssh *ssh, int id, int success, void *arg)
cleanup_exit(255);
}
- debug("%s: tunnel forward established, id=%d", __func__, id);
+ debug_f("tunnel forward established, id=%d", id);
forwarding_success();
}
@@ -1834,25 +1860,67 @@ ssh_init_stdio_forwarding(struct ssh *ssh)
if (options.stdio_forward_host == NULL)
return;
- debug3("%s: %s:%d", __func__, options.stdio_forward_host,
+ debug3_f("%s:%d", options.stdio_forward_host,
options.stdio_forward_port);
if ((in = dup(STDIN_FILENO)) == -1 ||
(out = dup(STDOUT_FILENO)) == -1)
- fatal("channel_connect_stdio_fwd: dup() in/out failed");
+ fatal_f("dup() in/out failed");
if ((c = channel_connect_stdio_fwd(ssh, options.stdio_forward_host,
- options.stdio_forward_port, in, out)) == NULL)
- fatal("%s: channel_connect_stdio_fwd failed", __func__);
+ options.stdio_forward_port, in, out,
+ CHANNEL_NONBLOCK_STDIO)) == NULL)
+ fatal_f("channel_connect_stdio_fwd failed");
channel_register_cleanup(ssh, c->self, client_cleanup_stdio_fwd, 0);
channel_register_open_confirm(ssh, c->self, ssh_stdio_confirm, NULL);
}
static void
+ssh_init_forward_permissions(struct ssh *ssh, const char *what, char **opens,
+ u_int num_opens)
+{
+ u_int i;
+ int port;
+ char *addr, *arg, *oarg, ch;
+ int where = FORWARD_LOCAL;
+
+ channel_clear_permission(ssh, FORWARD_ADM, where);
+ if (num_opens == 0)
+ return; /* permit any */
+
+ /* handle keywords: "any" / "none" */
+ if (num_opens == 1 && strcmp(opens[0], "any") == 0)
+ return;
+ if (num_opens == 1 && strcmp(opens[0], "none") == 0) {
+ channel_disable_admin(ssh, where);
+ return;
+ }
+ /* Otherwise treat it as a list of permitted host:port */
+ for (i = 0; i < num_opens; i++) {
+ oarg = arg = xstrdup(opens[i]);
+ ch = '\0';
+ addr = hpdelim2(&arg, &ch);
+ if (addr == NULL || ch == '/')
+ fatal_f("missing host in %s", what);
+ addr = cleanhostname(addr);
+ if (arg == NULL || ((port = permitopen_port(arg)) < 0))
+ fatal_f("bad port number in %s", what);
+ /* Send it to channels layer */
+ channel_add_permission(ssh, FORWARD_ADM,
+ where, addr, port);
+ free(oarg);
+ }
+}
+
+static void
ssh_init_forwarding(struct ssh *ssh, char **ifname)
{
int success = 0;
int i;
+ ssh_init_forward_permissions(ssh, "permitremoteopen",
+ options.permitted_remote_opens,
+ options.num_permitted_remote_opens);
+
if (options.exit_on_forward_failure)
forward_confirms_pending = 0; /* track pending requests */
/* Initiate local TCP/IP port forwardings. */
@@ -1915,7 +1983,7 @@ ssh_init_forwarding(struct ssh *ssh, char **ifname)
error("Could not request tunnel forwarding.");
}
if (forward_confirms_pending > 0) {
- debug("%s: expecting replies for %d forwards", __func__,
+ debug_f("expecting replies for %d forwards",
forward_confirms_pending);
}
}
@@ -1930,8 +1998,7 @@ check_agent_present(void)
if ((r = ssh_get_authentication_socket(NULL)) != 0) {
options.forward_agent = 0;
if (r != SSH_ERR_AGENT_NOT_PRESENT)
- debug("ssh_get_authentication_socket: %s",
- ssh_err(r));
+ debug_r(r, "ssh_get_authentication_socket");
}
}
}
@@ -1940,7 +2007,7 @@ static void
ssh_session2_setup(struct ssh *ssh, int id, int success, void *arg)
{
extern char **environ;
- const char *display;
+ const char *display, *term;
int r, interactive = tty_flag;
char *proto = NULL, *data = NULL;
@@ -1968,14 +2035,18 @@ ssh_session2_setup(struct ssh *ssh, int id, int success, void *arg)
debug("Requesting authentication agent forwarding.");
channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0);
if ((r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send packet");
}
/* Tell the packet module whether this is an interactive session. */
ssh_packet_set_interactive(ssh, interactive,
options.ip_qos_interactive, options.ip_qos_bulk);
- client_session2_setup(ssh, id, tty_flag, subsystem_flag, getenv("TERM"),
+ if ((term = lookup_env_in_list("TERM", options.setenv,
+ options.num_setenv)) == NULL || *term == '\0')
+ term = getenv("TERM");
+ client_session2_setup(ssh, id, tty_flag,
+ options.session_type == SESSION_TYPE_SUBSYSTEM, term,
NULL, fileno(stdin), command, environ);
}
@@ -1986,7 +2057,7 @@ ssh_session2_open(struct ssh *ssh)
Channel *c;
int window, packetmax, in, out, err;
- if (stdin_null_flag) {
+ if (options.stdin_null) {
in = open(_PATH_DEVNULL, O_RDONLY);
} else {
in = dup(STDIN_FILENO);
@@ -1997,14 +2068,6 @@ ssh_session2_open(struct ssh *ssh)
if (in == -1 || out == -1 || err == -1)
fatal("dup() in/out/err failed");
- /* enable nonblocking unless tty */
- if (!isatty(in))
- set_nonblock(in);
- if (!isatty(out))
- set_nonblock(out);
- if (!isatty(err))
- set_nonblock(err);
-
window = CHAN_SES_WINDOW_DEFAULT;
packetmax = CHAN_SES_PACKET_DEFAULT;
if (tty_flag) {
@@ -2014,12 +2077,12 @@ ssh_session2_open(struct ssh *ssh)
c = channel_new(ssh,
"session", SSH_CHANNEL_OPENING, in, out, err,
window, packetmax, CHAN_EXTENDED_WRITE,
- "client-session", /*nonblock*/0);
+ "client-session", CHANNEL_NONBLOCK_STDIO);
- debug3("%s: channel_new: %d", __func__, c->self);
+ debug3_f("channel_new: %d", c->self);
channel_send_open(ssh, c->self);
- if (!no_shell_flag)
+ if (options.session_type != SESSION_TYPE_NONE)
channel_register_open_confirm(ssh, c->self,
ssh_session2_setup, NULL);
@@ -2027,9 +2090,9 @@ ssh_session2_open(struct ssh *ssh)
}
static int
-ssh_session2(struct ssh *ssh, struct passwd *pw)
+ssh_session2(struct ssh *ssh, const struct ssh_conn_info *cinfo)
{
- int r, devnull, id = -1;
+ int r, id = -1;
char *cp, *tun_fwd_ifname = NULL;
/* XXX should be pre-session */
@@ -2042,11 +2105,7 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
debug3("expanding LocalCommand: %s", options.local_command);
cp = options.local_command;
options.local_command = percent_expand(cp,
- DEFAULT_CLIENT_PERCENT_EXPAND_ARGS,
- "d", pw->pw_dir,
- "h", host,
- "r", options.user,
- "u", pw->pw_name,
+ DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(cinfo),
"T", tun_fwd_ifname == NULL ? "NONE" : tun_fwd_ifname,
(char *)NULL);
debug3("expanded LocalCommand: %s", options.local_command);
@@ -2060,23 +2119,25 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
/*
* If we are in control persist mode and have a working mux listen
* socket, then prepare to background ourselves and have a foreground
- * client attach as a control slave.
+ * client attach as a control client.
* NB. we must save copies of the flags that we override for
- * the backgrounding, since we defer attachment of the slave until
+ * the backgrounding, since we defer attachment of the client until
* after the connection is fully established (in particular,
* async rfwd replies have been received for ExitOnForwardFailure).
*/
if (options.control_persist && muxserver_sock != -1) {
- ostdin_null_flag = stdin_null_flag;
- ono_shell_flag = no_shell_flag;
+ ostdin_null_flag = options.stdin_null;
+ osession_type = options.session_type;
orequest_tty = options.request_tty;
otty_flag = tty_flag;
- stdin_null_flag = 1;
- no_shell_flag = 1;
+ options.stdin_null = 1;
+ options.session_type = SESSION_TYPE_NONE;
tty_flag = 0;
- if (!fork_after_authentication_flag)
+ if (!options.fork_after_authentication &&
+ (osession_type != SESSION_TYPE_NONE ||
+ options.stdio_forward_host != NULL))
need_controlpersist_detach = 1;
- fork_after_authentication_flag = 1;
+ options.fork_after_authentication = 1;
}
/*
* ControlPersist mux listen socket setup failed, attempt the
@@ -2085,7 +2146,7 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
if (options.control_persist && muxserver_sock == -1)
ssh_init_stdio_forwarding(ssh);
- if (!no_shell_flag)
+ if (options.session_type != SESSION_TYPE_NONE)
id = ssh_session2_open(ssh);
else {
ssh_packet_set_interactive(ssh,
@@ -2095,14 +2156,14 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
/* If we don't expect to open a new session, then disallow it */
if (options.control_master == SSHCTL_MASTER_NO &&
- (datafellows & SSH_NEW_OPENSSH)) {
+ (ssh->compat & SSH_NEW_OPENSSH)) {
debug("Requesting no-more-sessions@openssh.com");
if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||
(r = sshpkt_put_cstring(ssh,
"no-more-sessions@openssh.com")) != 0 ||
(r = sshpkt_put_u8(ssh, 0)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send packet");
}
/* Execute a local command */
@@ -2116,21 +2177,14 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
* NB. this can only happen after LocalCommand has completed,
* as it may want to write to stdout.
*/
- if (!need_controlpersist_detach) {
- if ((devnull = open(_PATH_DEVNULL, O_WRONLY)) == -1)
- error("%s: open %s: %s", __func__,
- _PATH_DEVNULL, strerror(errno));
- if (dup2(devnull, STDOUT_FILENO) == -1)
- fatal("%s: dup2() stdout failed", __func__);
- if (devnull > STDERR_FILENO)
- close(devnull);
- }
+ if (!need_controlpersist_detach && stdfd_devnull(0, 1, 0) == -1)
+ error_f("stdfd_devnull failed");
/*
* If requested and we are not interested in replies to remote
* forwarding requests, then let ssh continue in the background.
*/
- if (fork_after_authentication_flag) {
+ if (options.fork_after_authentication) {
if (options.exit_on_forward_failure &&
options.num_remote_forwards > 0) {
debug("deferring postauth fork until remote forward "
@@ -2145,7 +2199,7 @@ ssh_session2(struct ssh *ssh, struct passwd *pw)
/* Loads all IdentityFile and CertificateFile keys */
static void
-load_public_identity_files(struct passwd *pw)
+load_public_identity_files(const struct ssh_conn_info *cinfo)
{
char *filename, *cp;
struct sshkey *public;
@@ -2201,8 +2255,7 @@ load_public_identity_files(struct passwd *pw)
continue;
}
cp = tilde_expand_filename(options.identity_files[i], getuid());
- filename = default_client_percent_expand(cp,
- pw->pw_dir, host, options.user, pw->pw_name);
+ filename = default_client_percent_dollar_expand(cp, cinfo);
free(cp);
check_load(sshkey_load_public(filename, &public, NULL),
filename, "pubkey");
@@ -2232,8 +2285,8 @@ load_public_identity_files(struct passwd *pw)
continue;
}
if (!sshkey_is_cert(public)) {
- debug("%s: key %s type %s is not a certificate",
- __func__, cp, sshkey_type(public));
+ debug_f("key %s type %s is not a certificate",
+ cp, sshkey_type(public));
sshkey_free(public);
free(cp);
continue;
@@ -2247,12 +2300,11 @@ load_public_identity_files(struct passwd *pw)
}
if (options.num_certificate_files > SSH_MAX_CERTIFICATE_FILES)
- fatal("%s: too many certificates", __func__);
+ fatal_f("too many certificates");
for (i = 0; i < options.num_certificate_files; i++) {
cp = tilde_expand_filename(options.certificate_files[i],
getuid());
- filename = default_client_percent_expand(cp,
- pw->pw_dir, host, options.user, pw->pw_name);
+ filename = default_client_percent_dollar_expand(cp, cinfo);
free(cp);
check_load(sshkey_load_public(filename, &public, NULL),
@@ -2266,8 +2318,8 @@ load_public_identity_files(struct passwd *pw)
continue;
}
if (!sshkey_is_cert(public)) {
- debug("%s: key %s type %s is not a certificate",
- __func__, filename, sshkey_type(public));
+ debug_f("key %s type %s is not a certificate",
+ filename, sshkey_type(public));
sshkey_free(public);
free(filename);
continue;
diff --git a/ssh.h b/ssh.h
index dda6f617e..8110c0602 100644
--- a/ssh.h
+++ b/ssh.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.h,v 1.89 2018/12/27 03:25:25 djm Exp $ */
+/* $OpenBSD: ssh.h,v 1.90 2020/07/14 23:57:01 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -68,6 +68,11 @@
#define SSH_ASKPASS_ENV "SSH_ASKPASS"
/*
+ * Environment variable to control whether or not askpass is used.
+ */
+#define SSH_ASKPASS_REQUIRE_ENV "SSH_ASKPASS_REQUIRE"
+
+/*
* Force host key length and server key length to differ by at least this
* many bits. This is to make double encryption with rsaref work.
*/
diff --git a/ssh2.h b/ssh2.h
index f2e37c96a..32ddae89b 100644
--- a/ssh2.h
+++ b/ssh2.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh2.h,v 1.18 2016/05/04 14:22:33 markus Exp $ */
+/* $OpenBSD: ssh2.h,v 1.19 2020/11/19 23:05:05 dtucker Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -25,7 +25,7 @@
*/
/*
- * draft-ietf-secsh-architecture-05.txt
+ * RFC4251:
*
* Transport layer protocol:
*
diff --git a/ssh_api.c b/ssh_api.c
index e0b195521..d3c661761 100644
--- a/ssh_api.c
+++ b/ssh_api.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh_api.c,v 1.19 2019/10/31 21:23:19 djm Exp $ */
+/* $OpenBSD: ssh_api.c,v 1.27 2021/04/03 06:18:41 djm Exp $ */
/*
* Copyright (c) 2012 Markus Friedl. All rights reserved.
*
@@ -54,20 +54,16 @@ int _ssh_host_key_sign(struct ssh *, struct sshkey *, struct sshkey *,
*/
int use_privsep = 0;
int mm_sshkey_sign(struct sshkey *, u_char **, u_int *,
- const u_char *, u_int, const char *, const char *, u_int);
+ const u_char *, u_int, const char *, const char *, const char *, u_int);
#ifdef WITH_OPENSSL
DH *mm_choose_dh(int, int, int);
#endif
-/* Define these two variables here so that they are part of the library */
-u_char *session_id2 = NULL;
-u_int session_id2_len = 0;
-
int
mm_sshkey_sign(struct sshkey *key, u_char **sigp, u_int *lenp,
- const u_char *data, u_int datalen, const char *alg, const char *sk_provider,
- u_int compat)
+ const u_char *data, u_int datalen, const char *alg,
+ const char *sk_provider, const char *sk_pin, u_int compat)
{
return (-1);
}
@@ -85,7 +81,7 @@ mm_choose_dh(int min, int nbits, int max)
int
ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params)
{
- char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
+ char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
struct ssh *ssh;
char **proposal;
static int called;
@@ -122,7 +118,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params)
# endif
#endif /* WITH_OPENSSL */
ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_server;
- ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server;
+ ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server;
ssh->kex->load_host_public_key=&_ssh_host_public_key;
ssh->kex->load_host_private_key=&_ssh_host_private_key;
ssh->kex->sign=&_ssh_host_key_sign;
@@ -140,7 +136,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params)
# endif
#endif /* WITH_OPENSSL */
ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client;
- ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client;
+ ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client;
ssh->kex->verify_host_key =&_ssh_verify_host_key;
}
*sshp = ssh;
@@ -152,7 +148,9 @@ ssh_free(struct ssh *ssh)
{
struct key_entry *k;
- ssh_packet_close(ssh);
+ if (ssh == NULL)
+ return;
+
/*
* we've only created the public keys variants in case we
* are a acting as a server.
@@ -167,8 +165,7 @@ ssh_free(struct ssh *ssh)
TAILQ_REMOVE(&ssh->private_keys, k, next);
free(k);
}
- if (ssh->kex)
- kex_free(ssh->kex);
+ ssh_packet_close(ssh);
free(ssh);
}
@@ -358,13 +355,13 @@ _ssh_read_banner(struct ssh *ssh, struct sshbuf *banner)
if (sshbuf_len(banner) >= 4 &&
memcmp(sshbuf_ptr(banner), "SSH-", 4) == 0)
break;
- debug("%s: %.*s", __func__, (int)sshbuf_len(banner),
+ debug_f("%.*s", (int)sshbuf_len(banner),
sshbuf_ptr(banner));
/* Accept lines before banner only on client */
if (ssh->kex->server || ++n > SSH_MAX_PRE_BANNER_LINES) {
bad:
if ((r = sshbuf_put(ssh_packet_get_output(ssh),
- mismatch, strlen(mismatch))) != 0)
+ mismatch, strlen(mismatch))) != 0)
return r;
return SSH_ERR_NO_PROTOCOL_VERSION;
}
@@ -391,7 +388,7 @@ _ssh_read_banner(struct ssh *ssh, struct sshbuf *banner)
debug("Remote protocol version %d.%d, remote software version %.100s",
remote_major, remote_minor, remote_version);
- ssh->compat = compat_datafellows(remote_version);
+ compat_banner(ssh, remote_version);
if (remote_major == 1 && remote_minor == 99) {
remote_major = 2;
remote_minor = 0;
@@ -471,9 +468,9 @@ _ssh_host_public_key(int type, int nid, struct ssh *ssh)
{
struct key_entry *k;
- debug3("%s: need %d", __func__, type);
+ debug3_f("need %d", type);
TAILQ_FOREACH(k, &ssh->public_keys, next) {
- debug3("%s: check %s", __func__, sshkey_type(k->key));
+ debug3_f("check %s", sshkey_type(k->key));
if (k->key->type == type &&
(type != KEY_ECDSA || k->key->ecdsa_nid == nid))
return (k->key);
@@ -486,9 +483,9 @@ _ssh_host_private_key(int type, int nid, struct ssh *ssh)
{
struct key_entry *k;
- debug3("%s: need %d", __func__, type);
+ debug3_f("need %d", type);
TAILQ_FOREACH(k, &ssh->private_keys, next) {
- debug3("%s: check %s", __func__, sshkey_type(k->key));
+ debug3_f("check %s", sshkey_type(k->key));
if (k->key->type == type &&
(type != KEY_ECDSA || k->key->ecdsa_nid == nid))
return (k->key);
@@ -501,9 +498,9 @@ _ssh_verify_host_key(struct sshkey *hostkey, struct ssh *ssh)
{
struct key_entry *k;
- debug3("%s: need %s", __func__, sshkey_type(hostkey));
+ debug3_f("need %s", sshkey_type(hostkey));
TAILQ_FOREACH(k, &ssh->public_keys, next) {
- debug3("%s: check %s", __func__, sshkey_type(k->key));
+ debug3_f("check %s", sshkey_type(k->key));
if (sshkey_equal_public(hostkey, k->key))
return (0); /* ok */
}
@@ -549,8 +546,8 @@ _ssh_order_hostkeyalgs(struct ssh *ssh)
}
}
if (*replace != '\0') {
- debug2("%s: orig/%d %s", __func__, ssh->kex->server, orig);
- debug2("%s: replace/%d %s", __func__, ssh->kex->server, replace);
+ debug2_f("orig/%d %s", ssh->kex->server, orig);
+ debug2_f("replace/%d %s", ssh->kex->server, replace);
free(orig);
proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = replace;
replace = NULL; /* owned by proposal */
@@ -569,5 +566,5 @@ _ssh_host_key_sign(struct ssh *ssh, struct sshkey *privkey,
const u_char *data, size_t dlen, const char *alg)
{
return sshkey_sign(privkey, signature, slen, data, dlen,
- alg, NULL, ssh->compat);
+ alg, NULL, NULL, ssh->compat);
}
diff --git a/ssh_config b/ssh_config
index 5e8ef548b..842ea866c 100644
--- a/ssh_config
+++ b/ssh_config
@@ -1,4 +1,4 @@
-# $OpenBSD: ssh_config,v 1.34 2019/02/04 02:39:42 dtucker Exp $
+# $OpenBSD: ssh_config,v 1.35 2020/07/17 03:43:42 dtucker Exp $
# This is the ssh client system-wide configuration file. See
# ssh_config(5) for more information. This file provides defaults for
@@ -43,3 +43,4 @@
# VisualHostKey no
# ProxyCommand ssh -q -W %h:%p gateway.example.com
# RekeyLimit 1G 1h
+# UserKnownHostsFile ~/.ssh/known_hosts.d/%k
diff --git a/ssh_config.5 b/ssh_config.5
index dc010ccbd..170125a0e 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.325 2020/04/11 20:20:09 jmc Exp $
-.Dd $Mdocdate: April 11 2020 $
+.\" $OpenBSD: ssh_config.5,v 1.366 2021/09/25 09:40:33 kn Exp $
+.Dd $Mdocdate: September 25 2021 $
.Dt SSH_CONFIG 5
.Os
.Sh NAME
@@ -245,13 +245,22 @@ option was specified to
If this option is set to
.Cm no ,
no keys are added to the agent.
+Alternately, this option may be specified as a time interval
+using the format described in the
+.Sx TIME FORMATS
+section of
+.Xr sshd_config 5
+to specify the key's lifetime in
+.Xr ssh-agent 1 ,
+after which it will automatically be removed.
The argument must be
-.Cm yes ,
-.Cm confirm ,
-.Cm ask ,
-or
.Cm no
-(the default).
+(the default),
+.Cm yes ,
+.Cm confirm
+(optionally followed by a time interval),
+.Cm ask
+or a time interval.
.It Cm AddressFamily
Specifies which address family to use when connecting.
Valid arguments are
@@ -332,6 +341,11 @@ again using the new target name to pick up any new configuration in matching
and
.Cm Match
stanzas.
+A value of
+.Cm none
+disables the use of a
+.Cm ProxyJump
+host.
.It Cm CanonicalizeMaxDots
Specifies the maximum number of dot characters in a hostname before
canonicalization is disabled.
@@ -358,15 +372,32 @@ to be canonicalized to names in the
or
.Qq *.c.example.com
domains.
+.Pp
+A single argument of
+.Qq none
+causes no CNAMEs to be considered for canonicalization.
+This is the default behaviour.
.It Cm CASignatureAlgorithms
Specifies which algorithms are allowed for signing of certificates
by certificate authorities (CAs).
The default is:
.Bd -literal -offset indent
-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
-ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
+ssh-ed25519,ecdsa-sha2-nistp256,
+ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+sk-ssh-ed25519@openssh.com,
+sk-ecdsa-sha2-nistp256@openssh.com,
+rsa-sha2-512,rsa-sha2-256
.Ed
.Pp
+If the specified list begins with a
+.Sq +
+character, then the specified algorithms will be appended to the default set
+instead of replacing them.
+If the specified list begins with a
+.Sq -
+character, then the specified algorithms (including wildcards) will be removed
+from the default set instead of replacing them.
+.Pp
.Xr ssh 1
will not accept host certificates signed using algorithms other than those
specified.
@@ -389,9 +420,11 @@ or
.Pp
Arguments to
.Cm CertificateFile
-may use the tilde syntax to refer to a user's home directory
-or the tokens described in the
+may use the tilde syntax to refer to a user's home directory,
+the tokens described in the
.Sx TOKENS
+section and environment variables as described in the
+.Sx ENVIRONMENT VARIABLES
section.
.Pp
It is possible to have multiple certificate files specified in
@@ -400,17 +433,9 @@ Multiple
.Cm CertificateFile
directives will add to the list of certificates used for
authentication.
-.It Cm ChallengeResponseAuthentication
-Specifies whether to use challenge-response authentication.
-The argument to this keyword must be
-.Cm yes
-(the default)
-or
-.Cm no .
.It Cm CheckHostIP
If set to
.Cm yes
-(the default),
.Xr ssh 1
will additionally check the host IP address in the
.Pa known_hosts
@@ -421,7 +446,8 @@ and will add addresses of destination hosts to
in the process, regardless of the setting of
.Cm StrictHostKeyChecking .
If the option is set to
-.Cm no ,
+.Cm no
+(the default),
the check will not be executed.
.It Cm Ciphers
Specifies the ciphers allowed and their order of preference.
@@ -551,9 +577,11 @@ section above or the string
to disable connection sharing.
Arguments to
.Cm ControlPath
-may use the tilde syntax to refer to a user's home directory
-or the tokens described in the
+may use the tilde syntax to refer to a user's home directory,
+the tokens described in the
.Sx TOKENS
+section and environment variables as described in the
+.Sx ENVIRONMENT VARIABLES
section.
It is recommended that any
.Cm ControlPath
@@ -669,6 +697,45 @@ Valid options are:
and
.Cm sha256
(the default).
+.It Cm ForkAfterAuthentication
+Requests
+.Nm ssh
+to go to background just before command execution.
+This is useful if
+.Nm ssh
+is going to ask for passwords or passphrases, but the user
+wants it in the background.
+This implies the
+.Cm StdinNull
+configuration option being set to
+.Dq yes .
+The recommended way to start X11 programs at a remote site is with
+something like
+.Ic ssh -f host xterm ,
+which is the same as
+.Ic ssh host xterm
+if the
+.Cm ForkAfterAuthentication
+configuration option is set to
+.Dq yes .
+.Pp
+If the
+.Cm ExitOnForwardFailure
+configuration option is set to
+.Dq yes ,
+then a client started with the
+.Cm ForkAfterAuthentication
+configuration option being set to
+.Dq yes
+will wait for all remote port forwards to be successfully established
+before placing itself in the background.
+The argument to this keyword must be
+.Cm yes
+(same as the
+.Fl f
+option) or
+.Cm no
+(the default).
.It Cm ForwardAgent
Specifies whether the connection to the authentication agent (if any)
will be forwarded to the remote machine.
@@ -787,87 +854,88 @@ Note that existing names and addresses in known hosts files
will not be converted automatically,
but may be manually hashed using
.Xr ssh-keygen 1 .
-.It Cm HostbasedAuthentication
-Specifies whether to try rhosts based authentication with public key
-authentication.
-The argument must be
-.Cm yes
-or
-.Cm no
-(the default).
-.It Cm HostbasedKeyTypes
-Specifies the key types that will be used for hostbased authentication
-as a comma-separated list of patterns.
+.It Cm HostbasedAcceptedAlgorithms
+Specifies the signature algorithms that will be used for hostbased
+authentication as a comma-separated list of patterns.
Alternately if the specified list begins with a
.Sq +
-character, then the specified key types will be appended to the default set
-instead of replacing them.
+character, then the specified signature algorithms will be appended
+to the default set instead of replacing them.
If the specified list begins with a
.Sq -
-character, then the specified key types (including wildcards) will be removed
-from the default set instead of replacing them.
+character, then the specified signature algorithms (including wildcards)
+will be removed from the default set instead of replacing them.
If the specified list begins with a
.Sq ^
-character, then the specified key types will be placed at the head of the
-default set.
+character, then the specified signature algorithms will be placed
+at the head of the default set.
The default for this option is:
.Bd -literal -offset 3n
+ssh-ed25519-cert-v01@openssh.com,
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ssh-ed25519-cert-v01@openssh.com,
sk-ssh-ed25519-cert-v01@openssh.com,
+sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,
rsa-sha2-256-cert-v01@openssh.com,
-ssh-rsa-cert-v01@openssh.com,
+ssh-ed25519,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+sk-ssh-ed25519@openssh.com,
sk-ecdsa-sha2-nistp256@openssh.com,
-ssh-ed25519,sk-ssh-ed25519@openssh.com,
-rsa-sha2-512,rsa-sha2-256,ssh-rsa
+rsa-sha2-512,rsa-sha2-256
.Ed
.Pp
The
.Fl Q
option of
.Xr ssh 1
-may be used to list supported key types.
+may be used to list supported signature algorithms.
+This was formerly named HostbasedKeyTypes.
+.It Cm HostbasedAuthentication
+Specifies whether to try rhosts based authentication with public key
+authentication.
+The argument must be
+.Cm yes
+or
+.Cm no
+(the default).
.It Cm HostKeyAlgorithms
-Specifies the host key algorithms
+Specifies the host key signature algorithms
that the client wants to use in order of preference.
Alternately if the specified list begins with a
.Sq +
-character, then the specified key types will be appended to the default set
-instead of replacing them.
+character, then the specified signature algorithms will be appended to
+the default set instead of replacing them.
If the specified list begins with a
.Sq -
-character, then the specified key types (including wildcards) will be removed
-from the default set instead of replacing them.
+character, then the specified signature algorithms (including wildcards)
+will be removed from the default set instead of replacing them.
If the specified list begins with a
.Sq ^
-character, then the specified key types will be placed at the head of the
-default set.
+character, then the specified signature algorithms will be placed
+at the head of the default set.
The default for this option is:
.Bd -literal -offset 3n
+ssh-ed25519-cert-v01@openssh.com,
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ssh-ed25519-cert-v01@openssh.com,
sk-ssh-ed25519-cert-v01@openssh.com,
+sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,
rsa-sha2-256-cert-v01@openssh.com,
-ssh-rsa-cert-v01@openssh.com,
+ssh-ed25519,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
sk-ecdsa-sha2-nistp256@openssh.com,
-ssh-ed25519,sk-ssh-ed25519@openssh.com,
-rsa-sha2-512,rsa-sha2-256,ssh-rsa
+sk-ssh-ed25519@openssh.com,
+rsa-sha2-512,rsa-sha2-256
.Ed
.Pp
If hostkeys are known for the destination host then this default is modified
to prefer their algorithms.
.Pp
-The list of available key types may also be obtained using
+The list of available signature algorithms may also be obtained using
.Qq ssh -Q HostKeyAlgorithms .
.It Cm HostKeyAlias
Specifies an alias that should be used instead of the
@@ -934,9 +1002,11 @@ the location of the socket.
.Pp
Arguments to
.Cm IdentityAgent
-may use the tilde syntax to refer to a user's home directory
-or the tokens described in the
+may use the tilde syntax to refer to a user's home directory,
+the tokens described in the
.Sx TOKENS
+section and environment variables as described in the
+.Sx ENVIRONMENT VARIABLES
section.
.It Cm IdentityFile
Specifies a file from which the user's DSA, ECDSA, authenticator-hosted ECDSA,
@@ -1004,6 +1074,7 @@ Multiple pathnames may be specified and each pathname may contain
wildcards and, for user configurations, shell-like
.Sq ~
references to user home directories.
+Wildcards will be expanded and processed in lexical order.
Files without absolute paths are assumed to be in
.Pa ~/.ssh
if included in a user configuration file or
@@ -1065,6 +1136,8 @@ The argument to this keyword must be
(the default)
or
.Cm no .
+.Cm ChallengeResponseAuthentication
+is a deprecated alias for this.
.It Cm KbdInteractiveDevices
Specifies the list of methods to use in keyboard-interactive authentication.
Multiple method names must be comma-separated.
@@ -1080,15 +1153,15 @@ Specifies the available KEX (Key Exchange) algorithms.
Multiple algorithms must be comma-separated.
If the specified list begins with a
.Sq +
-character, then the specified methods will be appended to the default set
+character, then the specified algorithms will be appended to the default set
instead of replacing them.
If the specified list begins with a
.Sq -
-character, then the specified methods (including wildcards) will be removed
+character, then the specified algorithms (including wildcards) will be removed
from the default set instead of replacing them.
If the specified list begins with a
.Sq ^
-character, then the specified methods will be placed at the head of the
+character, then the specified algorithms will be placed at the head of the
default set.
The default is:
.Bd -literal -offset indent
@@ -1102,6 +1175,31 @@ diffie-hellman-group14-sha256
.Pp
The list of available key exchange algorithms may also be obtained using
.Qq ssh -Q kex .
+.It Cm KnownHostsCommand
+Specifies a command to use to obtain a list of host keys, in addition to
+those listed in
+.Cm UserKnownHostsFile
+and
+.Cm GlobalKnownHostsFile .
+This command is executed after the files have been read.
+It may write host key lines to standard output in identical format to the
+usual files (described in the
+.Sx VERIFYING HOST KEYS
+section in
+.Xr ssh 1 ) .
+Arguments to
+.Cm KnownHostsCommand
+accept the tokens described in the
+.Sx TOKENS
+section.
+The command may be invoked multiple times per connection: once when preparing
+the preference list of host key algorithms to use, again to obtain the
+host key for the requested host name and, if
+.Cm CheckHostIP
+is enabled, one more time to obtain the host key matching the server's
+address.
+If the command exits abnormally or returns a non-zero exit status then the
+connection is terminated.
.It Cm LocalCommand
Specifies a command to execute on the local machine after successfully
connecting to the server.
@@ -1152,8 +1250,10 @@ indicates that the listening port be bound for local use only, while an
empty address or
.Sq *
indicates that the port should be available from all interfaces.
-Unix domain socket paths accept the tokens described in the
+Unix domain socket paths may use the tokens described in the
.Sx TOKENS
+section and environment variables as described in the
+.Sx ENVIRONMENT VARIABLES
section.
.It Cm LogLevel
Gives the verbosity level that is used when logging messages from
@@ -1163,6 +1263,23 @@ QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3.
The default is INFO.
DEBUG and DEBUG1 are equivalent.
DEBUG2 and DEBUG3 each specify higher levels of verbose output.
+.It Cm LogVerbose
+Specify one or more overrides to LogLevel.
+An override consists of a pattern lists that matches the source file, function
+and line number to force detailed logging for.
+For example, an override pattern of:
+.Bd -literal -offset indent
+kex.c:*:1000,*:kex_exchange_identification():*,packet.c:*
+.Ed
+.Pp
+would enable detailed logging for line 1000 of
+.Pa kex.c ,
+everything in the
+.Fn kex_exchange_identification
+function, and all code in the
+.Pa packet.c
+file.
+This option is intended for debugging and no overrides are enabled by default.
.It Cm MACs
Specifies the MAC (message authentication code) algorithms
in order of preference.
@@ -1227,6 +1344,42 @@ The argument must be
or
.Cm no
(the default).
+.It Cm PermitRemoteOpen
+Specifies the destinations to which remote TCP port forwarding is permitted when
+.Cm RemoteForward
+is used as a SOCKS proxy.
+The forwarding specification must be one of the following forms:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm PermitRemoteOpen
+.Sm off
+.Ar host : port
+.Sm on
+.It
+.Cm PermitRemoteOpen
+.Sm off
+.Ar IPv4_addr : port
+.Sm on
+.It
+.Cm PermitRemoteOpen
+.Sm off
+.Ar \&[ IPv6_addr \&] : port
+.Sm on
+.El
+.Pp
+Multiple forwards may be specified by separating them with whitespace.
+An argument of
+.Cm any
+can be used to remove all restrictions and permit any forwarding requests.
+An argument of
+.Cm none
+can be used to prohibit all forwarding requests.
+The wildcard
+.Sq *
+can be used for host or port to allow all hosts or ports respectively.
+Otherwise, no pattern matching or address lookups are performed on supplied
+names.
.It Cm PKCS11Provider
Specifies which PKCS#11 provider to use or
.Cm none
@@ -1307,6 +1460,9 @@ connection to the specified
.Cm ProxyJump
host and then establishing a
TCP forwarding to the ultimate target from there.
+Setting the host to
+.Cm none
+disables this option entirely.
.Pp
Note that this option will compete with the
.Cm ProxyCommand
@@ -1326,40 +1482,40 @@ will pass a connected file descriptor back to
instead of continuing to execute and pass data.
The default is
.Cm no .
-.It Cm PubkeyAcceptedKeyTypes
-Specifies the key types that will be used for public key authentication
-as a comma-separated list of patterns.
+.It Cm PubkeyAcceptedAlgorithms
+Specifies the signature algorithms that will be used for public key
+authentication as a comma-separated list of patterns.
If the specified list begins with a
.Sq +
-character, then the key types after it will be appended to the default
+character, then the algorithms after it will be appended to the default
instead of replacing it.
If the specified list begins with a
.Sq -
-character, then the specified key types (including wildcards) will be removed
+character, then the specified algorithms (including wildcards) will be removed
from the default set instead of replacing them.
If the specified list begins with a
.Sq ^
-character, then the specified key types will be placed at the head of the
+character, then the specified algorithms will be placed at the head of the
default set.
The default for this option is:
.Bd -literal -offset 3n
+ssh-ed25519-cert-v01@openssh.com,
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ssh-ed25519-cert-v01@openssh.com,
sk-ssh-ed25519-cert-v01@openssh.com,
+sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,
rsa-sha2-256-cert-v01@openssh.com,
-ssh-rsa-cert-v01@openssh.com,
+ssh-ed25519,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+sk-ssh-ed25519@openssh.com,
sk-ecdsa-sha2-nistp256@openssh.com,
-ssh-ed25519,sk-ssh-ed25519@openssh.com,
-rsa-sha2-512,rsa-sha2-256,ssh-rsa
+rsa-sha2-512,rsa-sha2-256
.Ed
.Pp
-The list of available key types may also be obtained using
-.Qq ssh -Q PubkeyAcceptedKeyTypes .
+The list of available signature algorithms may also be obtained using
+.Qq ssh -Q PubkeyAcceptedAlgorithms .
.It Cm PubkeyAuthentication
Specifies whether to try public key authentication.
The argument to this keyword must be
@@ -1369,7 +1525,7 @@ or
.Cm no .
.It Cm RekeyLimit
Specifies the maximum amount of data that may be transmitted before the
-session key is renegotiated, optionally followed a maximum amount of
+session key is renegotiated, optionally followed by a maximum amount of
time that may pass before the session key is renegotiated.
The first argument is specified in bytes and may have a suffix of
.Sq K ,
@@ -1417,14 +1573,19 @@ If forwarding to a specific destination then the second argument must be
or a Unix domain socket path,
otherwise if no destination argument is specified then the remote forwarding
will be established as a SOCKS proxy.
+When acting as a SOCKS proxy the destination of the connection can be
+restricted by
+.Cm PermitRemoteOpen .
.Pp
IPv6 addresses can be specified by enclosing addresses in square brackets.
Multiple forwardings may be specified, and additional
forwardings can be given on the command line.
Privileged ports can be forwarded only when
logging in as root on the remote machine.
-Unix domain socket paths accept the tokens described in the
+Unix domain socket paths may use the tokens described in the
.Sx TOKENS
+section and environment variables as described in the
+.Sx ENVIRONMENT VARIABLES
section.
.Pp
If the
@@ -1548,12 +1709,45 @@ will send a message through the encrypted
channel to request a response from the server.
The default
is 0, indicating that these messages will not be sent to the server.
+.It Cm SessionType
+May be used to either request invocation of a subsystem on the remote system,
+or to prevent the execution of a remote command at all.
+The latter is useful for just forwarding ports.
+The argument to this keyword must be
+.Cm none
+(same as the
+.Fl N
+option),
+.Cm subsystem
+(same as the
+.Fl s
+option) or
+.Cm default
+(shell or command execution).
.It Cm SetEnv
Directly specify one or more environment variables and their contents to
be sent to the server.
Similarly to
.Cm SendEnv ,
-the server must be prepared to accept the environment variable.
+with the exception of the
+.Ev TERM
+variable, the server must be prepared to accept the environment variable.
+.It Cm StdinNull
+Redirects stdin from
+.Pa /dev/null
+(actually, prevents reading from stdin).
+Either this or the equivalent
+.Fl n
+option must be used when
+.Nm ssh
+is run in the background.
+The argument to this keyword must be
+.Cm yes
+(same as the
+.Fl n
+option) or
+.Cm no
+(the default).
.It Cm StreamLocalBindMask
Sets the octal file creation mode mask
.Pq umask
@@ -1596,14 +1790,15 @@ This option forces the user to manually
add all new hosts.
.Pp
If this flag is set to
-.Dq accept-new
-then ssh will automatically add new host keys to the user
-known hosts files, but will not permit connections to hosts with
+.Cm accept-new
+then ssh will automatically add new host keys to the user's
+.Pa known_hosts
+file, but will not permit connections to hosts with
changed host keys.
If this flag is set to
-.Dq no
+.Cm no
or
-.Dq off ,
+.Cm off ,
ssh will automatically add new host keys to the user known hosts files
and allow connections to hosts with changed hostkeys to proceed,
subject to some restrictions.
@@ -1694,16 +1889,24 @@ or
This option allows learning alternate hostkeys for a server
and supports graceful key rotation by allowing a server to send replacement
public keys before old ones are removed.
+.Pp
Additional hostkeys are only accepted if the key used to authenticate the
-host was already trusted or explicitly accepted by the user.
+host was already trusted or explicitly accepted by the user, the host was
+authenticated via
+.Cm UserKnownHostsFile
+(i.e. not
+.Cm GlobalKnownHostsFile )
+and the host was authenticated using a plain key and not a certificate.
.Pp
.Cm UpdateHostKeys
is enabled by default if the user has not overridden the default
.Cm UserKnownHostsFile
-setting, otherwise
+setting and has not enabled
+.Cm VerifyHostKeyDNS ,
+otherwise
.Cm UpdateHostKeys
will be set to
-.Cm ask .
+.Cm no .
.Pp
If
.Cm UpdateHostKeys
@@ -1727,6 +1930,12 @@ having to remember to give the user name on the command line.
.It Cm UserKnownHostsFile
Specifies one or more files to use for the user
host key database, separated by whitespace.
+Each filename may use tilde notation to refer to the user's home directory,
+the tokens described in the
+.Sx TOKENS
+section and environment variables as described in the
+.Sx ENVIRONMENT VARIABLES
+section.
The default is
.Pa ~/.ssh/known_hosts ,
.Pa ~/.ssh/known_hosts2 .
@@ -1829,10 +2038,34 @@ A literal
Hash of %l%h%p%r.
.It %d
Local user's home directory.
+.It %f
+The fingerprint of the server's host key.
+.It %H
+The
+.Pa known_hosts
+hostname or address that is being searched for.
.It %h
The remote hostname.
+.It \%%I
+A string describing the reason for a
+.Cm KnownHostsCommand
+execution: either
+.Cm ADDRESS
+when looking up a host by address (only when
+.Cm CheckHostIP
+is enabled),
+.Cm HOSTNAME
+when searching by hostname, or
+.Cm ORDER
+when preparing the host key algorithm preference list to use for the
+destination host.
.It %i
The local user ID.
+.It %K
+The base64 encoded host key.
+.It %k
+The host key alias if specified, otherwise the original remote hostname given
+on the command line.
.It %L
The local hostname.
.It %l
@@ -1852,6 +2085,9 @@ network interface assigned if
tunnel forwarding was requested, or
.Qq NONE
otherwise.
+.It %t
+The type of the server host key, e.g.
+.Cm ssh-ed25519 .
.It %u
The local username.
.El
@@ -1860,12 +2096,17 @@ The local username.
.Cm ControlPath ,
.Cm IdentityAgent ,
.Cm IdentityFile ,
+.Cm KnownHostsCommand ,
.Cm LocalForward ,
.Cm Match exec ,
.Cm RemoteCommand ,
+.Cm RemoteForward ,
and
-.Cm RemoteForward
-accept the tokens %%, %C, %d, %h, %i, %L, %l, %n, %p, %r, and %u.
+.Cm UserKnownHostsFile
+accept the tokens %%, %C, %d, %h, %i, %k, %L, %l, %n, %p, %r, and %u.
+.Pp
+.Cm KnownHostsCommand
+additionally accepts the tokens %f, %H, %I, %K and %t.
.Pp
.Cm Hostname
accepts the tokens %% and %h.
@@ -1875,6 +2116,30 @@ accepts all tokens.
.Pp
.Cm ProxyCommand
accepts the tokens %%, %h, %n, %p, and %r.
+.Sh ENVIRONMENT VARIABLES
+Arguments to some keywords can be expanded at runtime from environment
+variables on the client by enclosing them in
+.Ic ${} ,
+for example
+.Ic ${HOME}/.ssh
+would refer to the user's .ssh directory.
+If a specified environment variable does not exist then an error will be
+returned and the setting for that keyword will be ignored.
+.Pp
+The keywords
+.Cm CertificateFile ,
+.Cm ControlPath ,
+.Cm IdentityAgent ,
+.Cm IdentityFile ,
+.Cm KnownHostsCommand ,
+and
+.Cm UserKnownHostsFile
+support environment variables.
+The keywords
+.Cm LocalForward
+and
+.Cm RemoteForward
+support environment variables only for Unix domain socket paths.
.Sh FILES
.Bl -tag -width Ds
.It Pa ~/.ssh/config
diff --git a/sshbuf-getput-basic.c b/sshbuf-getput-basic.c
index da834d008..9803fb5ed 100644
--- a/sshbuf-getput-basic.c
+++ b/sshbuf-getput-basic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshbuf-getput-basic.c,v 1.10 2019/12/13 19:09:37 djm Exp $ */
+/* $OpenBSD: sshbuf-getput-basic.c,v 1.11 2020/06/05 03:25:35 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller
*
@@ -338,6 +338,8 @@ sshbuf_put(struct sshbuf *buf, const void *v, size_t len)
int
sshbuf_putb(struct sshbuf *buf, const struct sshbuf *v)
{
+ if (v == NULL)
+ return 0;
return sshbuf_put(buf, sshbuf_ptr(v), sshbuf_len(v));
}
diff --git a/sshbuf-misc.c b/sshbuf-misc.c
index 9b5aa208c..80714d1f3 100644
--- a/sshbuf-misc.c
+++ b/sshbuf-misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshbuf-misc.c,v 1.14 2020/02/26 13:40:09 jsg Exp $ */
+/* $OpenBSD: sshbuf-misc.c,v 1.17 2021/08/11 05:21:32 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller
*
@@ -63,9 +63,9 @@ sshbuf_dump_data(const void *s, size_t len, FILE *f)
}
void
-sshbuf_dump(struct sshbuf *buf, FILE *f)
+sshbuf_dump(const struct sshbuf *buf, FILE *f)
{
- fprintf(f, "buffer %p len = %zu\n", buf, sshbuf_len(buf));
+ fprintf(f, "buffer len = %zu\n", sshbuf_len(buf));
sshbuf_dump_data(sshbuf_ptr(buf), sshbuf_len(buf), f);
}
@@ -167,6 +167,49 @@ sshbuf_b64tod(struct sshbuf *buf, const char *b64)
return 0;
}
+int
+sshbuf_dtourlb64(const struct sshbuf *d, struct sshbuf *b64, int wrap)
+{
+ int r = SSH_ERR_INTERNAL_ERROR;
+ u_char *p;
+ struct sshbuf *b = NULL;
+ size_t i, l;
+
+ if ((b = sshbuf_new()) == NULL)
+ return SSH_ERR_ALLOC_FAIL;
+ /* Encode using regular base64; we'll transform it once done */
+ if ((r = sshbuf_dtob64(d, b, wrap)) != 0)
+ goto out;
+ /* remove padding from end of encoded string*/
+ for (;;) {
+ l = sshbuf_len(b);
+ if (l <= 1 || sshbuf_ptr(b) == NULL) {
+ r = SSH_ERR_INTERNAL_ERROR;
+ goto out;
+ }
+ if (sshbuf_ptr(b)[l - 1] != '=')
+ break;
+ if ((r = sshbuf_consume_end(b, 1)) != 0)
+ goto out;
+ }
+ /* Replace characters with rfc4648 equivalents */
+ l = sshbuf_len(b);
+ if ((p = sshbuf_mutable_ptr(b)) == NULL) {
+ r = SSH_ERR_INTERNAL_ERROR;
+ goto out;
+ }
+ for (i = 0; i < l; i++) {
+ if (p[i] == '+')
+ p[i] = '-';
+ else if (p[i] == '/')
+ p[i] = '_';
+ }
+ r = sshbuf_putb(b64, b);
+ out:
+ sshbuf_free(b);
+ return r;
+}
+
char *
sshbuf_dup_string(struct sshbuf *buf)
{
diff --git a/sshbuf.h b/sshbuf.h
index 94392c8be..2ad0e61be 100644
--- a/sshbuf.h
+++ b/sshbuf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshbuf.h,v 1.21 2020/04/26 09:38:14 dtucker Exp $ */
+/* $OpenBSD: sshbuf.h,v 1.23 2020/06/22 05:54:10 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller
*
@@ -242,7 +242,7 @@ int sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v);
#endif /* WITH_OPENSSL */
/* Dump the contents of the buffer in a human-readable format */
-void sshbuf_dump(struct sshbuf *buf, FILE *f);
+void sshbuf_dump(const struct sshbuf *buf, FILE *f);
/* Dump specified memory in a human-readable format */
void sshbuf_dump_data(const void *s, size_t len, FILE *f);
@@ -253,6 +253,8 @@ char *sshbuf_dtob16(struct sshbuf *buf);
/* Encode the contents of the buffer as base64 */
char *sshbuf_dtob64_string(const struct sshbuf *buf, int wrap);
int sshbuf_dtob64(const struct sshbuf *d, struct sshbuf *b64, int wrap);
+/* RFC4648 "base64url" encoding variant */
+int sshbuf_dtourlb64(const struct sshbuf *d, struct sshbuf *b64, int wrap);
/* Decode base64 data and append it to the buffer */
int sshbuf_b64tod(struct sshbuf *buf, const char *b64);
diff --git a/sshconnect.c b/sshconnect.c
index af08be415..fcf87bb76 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect.c,v 1.329 2020/03/13 04:01:56 djm Exp $ */
+/* $OpenBSD: sshconnect.c,v 1.355 2021/07/02 05:11:21 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -30,6 +30,7 @@
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <netdb.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
@@ -89,11 +90,14 @@ expand_proxy_command(const char *proxy_command, const char *user,
const char *host, const char *host_arg, int port)
{
char *tmp, *ret, strport[NI_MAXSERV];
+ const char *keyalias = options.host_key_alias ?
+ options.host_key_alias : host_arg;
snprintf(strport, sizeof strport, "%d", port);
xasprintf(&tmp, "exec %s", proxy_command);
ret = percent_expand(tmp,
"h", host,
+ "k", keyalias,
"n", host_arg,
"p", strport,
"r", options.user,
@@ -102,24 +106,6 @@ expand_proxy_command(const char *proxy_command, const char *user,
return ret;
}
-static void
-stderr_null(void)
-{
- int devnull;
-
- if ((devnull = open(_PATH_DEVNULL, O_WRONLY)) == -1) {
- error("Can't open %s for stderr redirection: %s",
- _PATH_DEVNULL, strerror(errno));
- return;
- }
- if (devnull == STDERR_FILENO)
- return;
- if (dup2(devnull, STDERR_FILENO) == -1)
- error("Cannot redirect stderr to %s", _PATH_DEVNULL);
- if (devnull > STDERR_FILENO)
- close(devnull);
-}
-
/*
* Connect to the given ssh server using a proxy command that passes a
* a connected fd back to us.
@@ -166,8 +152,8 @@ ssh_proxy_fdpass_connect(struct ssh *ssh, const char *host,
* error messages may be printed on the user's terminal.
*/
if (!debug_flag && options.control_path != NULL &&
- options.control_persist)
- stderr_null();
+ options.control_persist && stdfd_devnull(0, 0, 1) == -1)
+ error_f("stdfd_devnull failed");
argv[0] = shell;
argv[1] = "-c";
@@ -249,16 +235,18 @@ ssh_proxy_connect(struct ssh *ssh, const char *host, const char *host_arg,
* error messages may be printed on the user's terminal.
*/
if (!debug_flag && options.control_path != NULL &&
- options.control_persist)
- stderr_null();
+ options.control_persist && stdfd_devnull(0, 0, 1) == -1)
+ error_f("stdfd_devnull failed");
argv[0] = shell;
argv[1] = "-c";
argv[2] = command_string;
argv[3] = NULL;
- /* Execute the proxy command. Note that we gave up any
- extra privileges above. */
+ /*
+ * Execute the proxy command. Note that we gave up any
+ * extra privileges above.
+ */
ssh_signal(SIGPIPE, SIG_DFL);
execv(argv[0], argv);
perror(argv[0]);
@@ -329,8 +317,7 @@ check_ifaddrs(const char *ifname, int af, const struct ifaddrs *ifaddrs,
htonl(INADDR_LOOPBACK))
continue;
if (*rlenp < sizeof(struct sockaddr_in)) {
- error("%s: v4 addr doesn't fit",
- __func__);
+ error_f("v4 addr doesn't fit");
return -1;
}
*rlenp = sizeof(struct sockaddr_in);
@@ -344,8 +331,7 @@ check_ifaddrs(const char *ifname, int af, const struct ifaddrs *ifaddrs,
IN6_IS_ADDR_LOOPBACK(v6addr)))
continue;
if (*rlenp < sizeof(struct sockaddr_in6)) {
- error("%s: v6 addr doesn't fit",
- __func__);
+ error_f("v6 addr doesn't fit");
return -1;
}
*rlenp = sizeof(struct sockaddr_in6);
@@ -380,6 +366,10 @@ ssh_create_socket(struct addrinfo *ai)
}
fcntl(sock, F_SETFD, FD_CLOEXEC);
+ /* Use interactive QOS (if specified) until authentication completed */
+ if (options.ip_qos_interactive != INT_MAX)
+ set_sock_tos(sock, options.ip_qos_interactive);
+
/* Bind the socket to an alternative local IP address */
if (options.bind_address == NULL && options.bind_interface == NULL)
return sock;
@@ -406,14 +396,14 @@ ssh_create_socket(struct addrinfo *ai)
#ifdef HAVE_IFADDRS_H
if ((r = getifaddrs(&ifaddrs)) != 0) {
error("getifaddrs: %s: %s", options.bind_interface,
- strerror(errno));
+ strerror(errno));
goto fail;
}
bindaddrlen = sizeof(bindaddr);
if (check_ifaddrs(options.bind_interface, ai->ai_family,
ifaddrs, &bindaddr, &bindaddrlen) != 0) {
logit("getifaddrs: %s: no suitable addresses",
- options.bind_interface);
+ options.bind_interface);
goto fail;
}
#else
@@ -422,15 +412,14 @@ ssh_create_socket(struct addrinfo *ai)
}
if ((r = getnameinfo((struct sockaddr *)&bindaddr, bindaddrlen,
ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST)) != 0) {
- error("%s: getnameinfo failed: %s", __func__,
- ssh_gai_strerror(r));
+ error_f("getnameinfo failed: %s", ssh_gai_strerror(r));
goto fail;
}
if (bind(sock, (struct sockaddr *)&bindaddr, bindaddrlen) != 0) {
error("bind %s: %s", ntop, strerror(errno));
goto fail;
}
- debug("%s: bound to %s", __func__, ntop);
+ debug_f("bound to %s", ntop);
/* success */
goto out;
fail:
@@ -457,15 +446,15 @@ fail:
*/
static int
ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop,
- struct sockaddr_storage *hostaddr, u_short port, int family,
- int connection_attempts, int *timeout_ms, int want_keepalive)
+ struct sockaddr_storage *hostaddr, u_short port, int connection_attempts,
+ int *timeout_ms, int want_keepalive)
{
int on = 1, saved_timeout_ms = *timeout_ms;
int oerrno, sock = -1, attempt;
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
struct addrinfo *ai;
- debug2("%s", __func__);
+ debug3_f("entering");
memset(ntop, 0, sizeof(ntop));
memset(strport, 0, sizeof(strport));
@@ -489,7 +478,7 @@ ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop,
ntop, sizeof(ntop), strport, sizeof(strport),
NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
oerrno = errno;
- error("%s: getnameinfo failed", __func__);
+ error_f("getnameinfo failed");
errno = oerrno;
continue;
}
@@ -548,19 +537,19 @@ ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop,
int
ssh_connect(struct ssh *ssh, const char *host, const char *host_arg,
struct addrinfo *addrs, struct sockaddr_storage *hostaddr, u_short port,
- int family, int connection_attempts, int *timeout_ms, int want_keepalive)
+ int connection_attempts, int *timeout_ms, int want_keepalive)
{
int in, out;
if (options.proxy_command == NULL) {
return ssh_connect_direct(ssh, host, addrs, hostaddr, port,
- family, connection_attempts, timeout_ms, want_keepalive);
+ connection_attempts, timeout_ms, want_keepalive);
} else if (strcmp(options.proxy_command, "-") == 0) {
if ((in = dup(STDIN_FILENO)) == -1 ||
(out = dup(STDOUT_FILENO)) == -1) {
if (in >= 0)
close(in);
- error("%s: dup() in/out failed", __func__);
+ error_f("dup() in/out failed");
return -1; /* ssh_packet_set_connection logs error */
}
if ((ssh_packet_set_connection(ssh, in, out)) == NULL)
@@ -594,7 +583,7 @@ confirm(const char *prompt, const char *fingerprint)
if (p[0] == '\0' || strcasecmp(p, "no") == 0)
ret = 0;
else if (strcasecmp(p, "yes") == 0 || (fingerprint != NULL &&
- strcasecmp(p, fingerprint) == 0))
+ strcmp(p, fingerprint) == 0))
ret = 1;
free(cp);
if (ret != -1)
@@ -603,32 +592,6 @@ confirm(const char *prompt, const char *fingerprint)
}
static int
-check_host_cert(const char *host, const struct sshkey *key)
-{
- const char *reason;
- int r;
-
- if (sshkey_cert_check_authority(key, 1, 0, host, &reason) != 0) {
- error("%s", reason);
- return 0;
- }
- if (sshbuf_len(key->cert->critical) != 0) {
- error("Certificate for %s contains unsupported "
- "critical options(s)", host);
- return 0;
- }
- if ((r = sshkey_check_cert_sigtype(key,
- options.ca_sign_algorithms)) != 0) {
- logit("%s: certificate signature algorithm %s: %s", __func__,
- (key->cert == NULL || key->cert->signature_type == NULL) ?
- "(null)" : key->cert->signature_type, ssh_err(r));
- return 0;
- }
-
- return 1;
-}
-
-static int
sockaddr_is_local(struct sockaddr *hostaddr)
{
switch (hostaddr->sa_family) {
@@ -677,7 +640,7 @@ get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr,
if (options.proxy_command == NULL) {
if (getnameinfo(hostaddr, addrlen,
ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0)
- fatal("%s: getnameinfo failed", __func__);
+ fatal_f("getnameinfo failed");
*hostfile_ipaddr = put_host_port(ntop, port);
} else {
*hostfile_ipaddr = xstrdup("<no hostip for proxy "
@@ -701,6 +664,257 @@ get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr,
}
}
+/* returns non-zero if path appears in hostfiles, or 0 if not. */
+static int
+path_in_hostfiles(const char *path, char **hostfiles, u_int num_hostfiles)
+{
+ u_int i;
+
+ for (i = 0; i < num_hostfiles; i++) {
+ if (strcmp(path, hostfiles[i]) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+struct find_by_key_ctx {
+ const char *host, *ip;
+ const struct sshkey *key;
+ char **names;
+ u_int nnames;
+};
+
+/* Try to replace home directory prefix (per $HOME) with a ~/ sequence */
+static char *
+try_tilde_unexpand(const char *path)
+{
+ char *home, *ret = NULL;
+ size_t l;
+
+ if (*path != '/')
+ return xstrdup(path);
+ if ((home = getenv("HOME")) == NULL || (l = strlen(home)) == 0)
+ return xstrdup(path);
+ if (strncmp(path, home, l) != 0)
+ return xstrdup(path);
+ /*
+ * ensure we have matched on a path boundary: either the $HOME that
+ * we just compared ends with a '/' or the next character of the path
+ * must be a '/'.
+ */
+ if (home[l - 1] != '/' && path[l] != '/')
+ return xstrdup(path);
+ if (path[l] == '/')
+ l++;
+ xasprintf(&ret, "~/%s", path + l);
+ return ret;
+}
+
+static int
+hostkeys_find_by_key_cb(struct hostkey_foreach_line *l, void *_ctx)
+{
+ struct find_by_key_ctx *ctx = (struct find_by_key_ctx *)_ctx;
+ char *path;
+
+ /* we are looking for keys with names that *do not* match */
+ if ((l->match & HKF_MATCH_HOST) != 0)
+ return 0;
+ /* not interested in marker lines */
+ if (l->marker != MRK_NONE)
+ return 0;
+ /* we are only interested in exact key matches */
+ if (l->key == NULL || !sshkey_equal(ctx->key, l->key))
+ return 0;
+ path = try_tilde_unexpand(l->path);
+ debug_f("found matching key in %s:%lu", path, l->linenum);
+ ctx->names = xrecallocarray(ctx->names,
+ ctx->nnames, ctx->nnames + 1, sizeof(*ctx->names));
+ xasprintf(&ctx->names[ctx->nnames], "%s:%lu: %s", path, l->linenum,
+ strncmp(l->hosts, HASH_MAGIC, strlen(HASH_MAGIC)) == 0 ?
+ "[hashed name]" : l->hosts);
+ ctx->nnames++;
+ free(path);
+ return 0;
+}
+
+static int
+hostkeys_find_by_key_hostfile(const char *file, const char *which,
+ struct find_by_key_ctx *ctx)
+{
+ int r;
+
+ debug3_f("trying %s hostfile \"%s\"", which, file);
+ if ((r = hostkeys_foreach(file, hostkeys_find_by_key_cb, ctx,
+ ctx->host, ctx->ip, HKF_WANT_PARSE_KEY, 0)) != 0) {
+ if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT) {
+ debug_f("hostkeys file %s does not exist", file);
+ return 0;
+ }
+ error_fr(r, "hostkeys_foreach failed for %s", file);
+ return r;
+ }
+ return 0;
+}
+
+/*
+ * Find 'key' in known hosts file(s) that do not match host/ip.
+ * Used to display also-known-as information for previously-unseen hostkeys.
+ */
+static void
+hostkeys_find_by_key(const char *host, const char *ip, const struct sshkey *key,
+ char **user_hostfiles, u_int num_user_hostfiles,
+ char **system_hostfiles, u_int num_system_hostfiles,
+ char ***names, u_int *nnames)
+{
+ struct find_by_key_ctx ctx = {0, 0, 0, 0, 0};
+ u_int i;
+
+ *names = NULL;
+ *nnames = 0;
+
+ if (key == NULL || sshkey_is_cert(key))
+ return;
+
+ ctx.host = host;
+ ctx.ip = ip;
+ ctx.key = key;
+
+ for (i = 0; i < num_user_hostfiles; i++) {
+ if (hostkeys_find_by_key_hostfile(user_hostfiles[i],
+ "user", &ctx) != 0)
+ goto fail;
+ }
+ for (i = 0; i < num_system_hostfiles; i++) {
+ if (hostkeys_find_by_key_hostfile(system_hostfiles[i],
+ "system", &ctx) != 0)
+ goto fail;
+ }
+ /* success */
+ *names = ctx.names;
+ *nnames = ctx.nnames;
+ ctx.names = NULL;
+ ctx.nnames = 0;
+ return;
+ fail:
+ for (i = 0; i < ctx.nnames; i++)
+ free(ctx.names[i]);
+ free(ctx.names);
+}
+
+#define MAX_OTHER_NAMES 8 /* Maximum number of names to list */
+static char *
+other_hostkeys_message(const char *host, const char *ip,
+ const struct sshkey *key,
+ char **user_hostfiles, u_int num_user_hostfiles,
+ char **system_hostfiles, u_int num_system_hostfiles)
+{
+ char *ret = NULL, **othernames = NULL;
+ u_int i, n, num_othernames = 0;
+
+ hostkeys_find_by_key(host, ip, key,
+ user_hostfiles, num_user_hostfiles,
+ system_hostfiles, num_system_hostfiles,
+ &othernames, &num_othernames);
+ if (num_othernames == 0)
+ return xstrdup("This key is not known by any other names");
+
+ xasprintf(&ret, "This host key is known by the following other "
+ "names/addresses:");
+
+ n = num_othernames;
+ if (n > MAX_OTHER_NAMES)
+ n = MAX_OTHER_NAMES;
+ for (i = 0; i < n; i++) {
+ xextendf(&ret, "\n", " %s", othernames[i]);
+ }
+ if (n < num_othernames) {
+ xextendf(&ret, "\n", " (%d additional names omitted)",
+ num_othernames - n);
+ }
+ for (i = 0; i < num_othernames; i++)
+ free(othernames[i]);
+ free(othernames);
+ return ret;
+}
+
+void
+load_hostkeys_command(struct hostkeys *hostkeys, const char *command_template,
+ const char *invocation, const struct ssh_conn_info *cinfo,
+ const struct sshkey *host_key, const char *hostfile_hostname)
+{
+ int r, i, ac = 0;
+ char *key_fp = NULL, *keytext = NULL, *tmp;
+ char *command = NULL, *tag = NULL, **av = NULL;
+ FILE *f = NULL;
+ pid_t pid;
+ void (*osigchld)(int);
+
+ xasprintf(&tag, "KnownHostsCommand-%s", invocation);
+
+ if (host_key != NULL) {
+ if ((key_fp = sshkey_fingerprint(host_key,
+ options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
+ fatal_f("sshkey_fingerprint failed");
+ if ((r = sshkey_to_base64(host_key, &keytext)) != 0)
+ fatal_fr(r, "sshkey_to_base64 failed");
+ }
+ /*
+ * NB. all returns later this function should go via "out" to
+ * ensure the original SIGCHLD handler is restored properly.
+ */
+ osigchld = ssh_signal(SIGCHLD, SIG_DFL);
+
+ /* Turn the command into an argument vector */
+ if (argv_split(command_template, &ac, &av, 0) != 0) {
+ error("%s \"%s\" contains invalid quotes", tag,
+ command_template);
+ goto out;
+ }
+ if (ac == 0) {
+ error("%s \"%s\" yielded no arguments", tag,
+ command_template);
+ goto out;
+ }
+ for (i = 1; i < ac; i++) {
+ tmp = percent_dollar_expand(av[i],
+ DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(cinfo),
+ "H", hostfile_hostname,
+ "I", invocation,
+ "t", host_key == NULL ? "NONE" : sshkey_ssh_name(host_key),
+ "f", key_fp == NULL ? "NONE" : key_fp,
+ "K", keytext == NULL ? "NONE" : keytext,
+ (char *)NULL);
+ if (tmp == NULL)
+ fatal_f("percent_expand failed");
+ free(av[i]);
+ av[i] = tmp;
+ }
+ /* Prepare a printable command for logs, etc. */
+ command = argv_assemble(ac, av);
+
+ if ((pid = subprocess(tag, command, ac, av, &f,
+ SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_UNSAFE_PATH|
+ SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL)) == 0)
+ goto out;
+
+ load_hostkeys_file(hostkeys, hostfile_hostname, tag, f, 1);
+
+ if (exited_cleanly(pid, tag, command, 0) != 0)
+ fatal("KnownHostsCommand failed");
+
+ out:
+ if (f != NULL)
+ fclose(f);
+ ssh_signal(SIGCHLD, osigchld);
+ for (i = 0; i < ac; i++)
+ free(av[i]);
+ free(av);
+ free(tag);
+ free(command);
+ free(key_fp);
+ free(keytext);
+}
+
/*
* check whether the supplied host key is valid, return -1 if the key
* is not valid. user_hostfile[0] will not be updated if 'readonly' is true.
@@ -709,19 +923,20 @@ get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr,
#define RDONLY 1
#define ROQUIET 2
static int
-check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
- struct sshkey *host_key, int readonly,
+check_host_key(char *hostname, const struct ssh_conn_info *cinfo,
+ struct sockaddr *hostaddr, u_short port,
+ struct sshkey *host_key, int readonly, int clobber_port,
char **user_hostfiles, u_int num_user_hostfiles,
- char **system_hostfiles, u_int num_system_hostfiles)
+ char **system_hostfiles, u_int num_system_hostfiles,
+ const char *hostfile_command)
{
- HostStatus host_status;
- HostStatus ip_status;
+ HostStatus host_status = -1, ip_status = -1;
struct sshkey *raw_key = NULL;
char *ip = NULL, *host = NULL;
char hostline[1000], *hostp, *fp, *ra;
char msg[1024];
- const char *type;
- const struct hostkey_entry *host_found, *ip_found;
+ const char *type, *fail_reason;
+ const struct hostkey_entry *host_found = NULL, *ip_found = NULL;
int len, cancelled_forwarding = 0, confirmed;
int local = sockaddr_is_local(hostaddr);
int r, want_cert = sshkey_is_cert(host_key), host_ip_differ = 0;
@@ -741,6 +956,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
options.host_key_alias == NULL) {
debug("Forcing accepting of host key for "
"loopback/localhost.");
+ options.update_hostkeys = 0;
return 0;
}
@@ -748,7 +964,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
* Prepare the hostname and address strings used for hostkey lookup.
* In some cases, these will have a port number appended.
*/
- get_hostfile_hostname_ipaddr(hostname, hostaddr, port, &host, &ip);
+ get_hostfile_hostname_ipaddr(hostname, hostaddr,
+ clobber_port ? 0 : port, &host, &ip);
/*
* Turn off check_host_ip if the connection is to localhost, via proxy
@@ -760,17 +977,25 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
host_hostkeys = init_hostkeys();
for (i = 0; i < num_user_hostfiles; i++)
- load_hostkeys(host_hostkeys, host, user_hostfiles[i]);
+ load_hostkeys(host_hostkeys, host, user_hostfiles[i], 0);
for (i = 0; i < num_system_hostfiles; i++)
- load_hostkeys(host_hostkeys, host, system_hostfiles[i]);
+ load_hostkeys(host_hostkeys, host, system_hostfiles[i], 0);
+ if (hostfile_command != NULL && !clobber_port) {
+ load_hostkeys_command(host_hostkeys, hostfile_command,
+ "HOSTNAME", cinfo, host_key, host);
+ }
ip_hostkeys = NULL;
if (!want_cert && options.check_host_ip) {
ip_hostkeys = init_hostkeys();
for (i = 0; i < num_user_hostfiles; i++)
- load_hostkeys(ip_hostkeys, ip, user_hostfiles[i]);
+ load_hostkeys(ip_hostkeys, ip, user_hostfiles[i], 0);
for (i = 0; i < num_system_hostfiles; i++)
- load_hostkeys(ip_hostkeys, ip, system_hostfiles[i]);
+ load_hostkeys(ip_hostkeys, ip, system_hostfiles[i], 0);
+ if (hostfile_command != NULL && !clobber_port) {
+ load_hostkeys_command(ip_hostkeys, hostfile_command,
+ "ADDRESS", cinfo, host_key, ip);
+ }
}
retry:
@@ -786,6 +1011,14 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
&host_found);
/*
+ * If there are no hostfiles, or if the hostkey was found via
+ * KnownHostsCommand, then don't try to touch the disk.
+ */
+ if (!readonly && (num_user_hostfiles == 0 ||
+ (host_found != NULL && host_found->note != 0)))
+ readonly = RDONLY;
+
+ /*
* Also perform check for the ip address, skip the check if we are
* localhost, looking for a certificate, or the hostname was an ip
* address to begin with.
@@ -808,10 +1041,40 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
host, type, want_cert ? "certificate" : "key");
debug("Found %s in %s:%lu", want_cert ? "CA key" : "key",
host_found->file, host_found->line);
- if (want_cert &&
- !check_host_cert(options.host_key_alias == NULL ?
- hostname : options.host_key_alias, host_key))
- goto fail;
+ if (want_cert) {
+ if (sshkey_cert_check_host(host_key,
+ options.host_key_alias == NULL ?
+ hostname : options.host_key_alias, 0,
+ options.ca_sign_algorithms, &fail_reason) != 0) {
+ error("%s", fail_reason);
+ goto fail;
+ }
+ /*
+ * Do not attempt hostkey update if a certificate was
+ * successfully matched.
+ */
+ if (options.update_hostkeys != 0) {
+ options.update_hostkeys = 0;
+ debug3_f("certificate host key in use; "
+ "disabling UpdateHostkeys");
+ }
+ }
+ /* Turn off UpdateHostkeys if key was in system known_hosts */
+ if (options.update_hostkeys != 0 &&
+ (path_in_hostfiles(host_found->file,
+ system_hostfiles, num_system_hostfiles) ||
+ (ip_status == HOST_OK && ip_found != NULL &&
+ path_in_hostfiles(ip_found->file,
+ system_hostfiles, num_system_hostfiles)))) {
+ options.update_hostkeys = 0;
+ debug3_f("host key found in GlobalKnownHostsFile; "
+ "disabling UpdateHostkeys");
+ }
+ if (options.update_hostkeys != 0 && host_found->note) {
+ options.update_hostkeys = 0;
+ debug3_f("host key found via KnownHostsCommand; "
+ "disabling UpdateHostkeys");
+ }
if (options.check_host_ip && ip_status == HOST_NEW) {
if (readonly || want_cert)
logit("%s host key for IP address "
@@ -833,7 +1096,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
ra = sshkey_fingerprint(host_key,
options.fingerprint_hash, SSH_FP_RANDOMART);
if (fp == NULL || ra == NULL)
- fatal("%s: sshkey_fingerprint fail", __func__);
+ fatal_f("sshkey_fingerprint failed");
logit("Host key fingerprint is %s\n%s", fp, ra);
free(ra);
free(fp);
@@ -842,11 +1105,13 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
break;
case HOST_NEW:
if (options.host_key_alias == NULL && port != 0 &&
- port != SSH_DEFAULT_PORT) {
+ port != SSH_DEFAULT_PORT && !clobber_port) {
debug("checking without port identifier");
- if (check_host_key(hostname, hostaddr, 0, host_key,
- ROQUIET, user_hostfiles, num_user_hostfiles,
- system_hostfiles, num_system_hostfiles) == 0) {
+ if (check_host_key(hostname, cinfo, hostaddr, 0,
+ host_key, ROQUIET, 1,
+ user_hostfiles, num_user_hostfiles,
+ system_hostfiles, num_system_hostfiles,
+ hostfile_command) == 0) {
debug("found matching key w/out port");
break;
}
@@ -866,45 +1131,48 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
goto fail;
} else if (options.strict_host_key_checking ==
SSH_STRICT_HOSTKEY_ASK) {
- char msg1[1024], msg2[1024];
+ char *msg1 = NULL, *msg2 = NULL;
+
+ xasprintf(&msg1, "The authenticity of host "
+ "'%.200s (%s)' can't be established", host, ip);
+
+ if (show_other_keys(host_hostkeys, host_key)) {
+ xextendf(&msg1, "\n", "but keys of different "
+ "type are already known for this host.");
+ } else
+ xextendf(&msg1, "", ".");
- if (show_other_keys(host_hostkeys, host_key))
- snprintf(msg1, sizeof(msg1),
- "\nbut keys of different type are already"
- " known for this host.");
- else
- snprintf(msg1, sizeof(msg1), ".");
- /* The default */
fp = sshkey_fingerprint(host_key,
options.fingerprint_hash, SSH_FP_DEFAULT);
ra = sshkey_fingerprint(host_key,
options.fingerprint_hash, SSH_FP_RANDOMART);
if (fp == NULL || ra == NULL)
- fatal("%s: sshkey_fingerprint fail", __func__);
- msg2[0] = '\0';
+ fatal_f("sshkey_fingerprint failed");
+ xextendf(&msg1, "\n", "%s key fingerprint is %s.",
+ type, fp);
+ if (options.visual_host_key)
+ xextendf(&msg1, "\n", "%s", ra);
if (options.verify_host_key_dns) {
- if (matching_host_key_dns)
- snprintf(msg2, sizeof(msg2),
- "Matching host key fingerprint"
- " found in DNS.\n");
- else
- snprintf(msg2, sizeof(msg2),
- "No matching host key fingerprint"
- " found in DNS.\n");
+ xextendf(&msg1, "\n",
+ "%s host key fingerprint found in DNS.",
+ matching_host_key_dns ?
+ "Matching" : "No matching");
}
- snprintf(msg, sizeof(msg),
- "The authenticity of host '%.200s (%s)' can't be "
- "established%s\n"
- "%s key fingerprint is %s.%s%s\n%s"
+ /* msg2 informs for other names matching this key */
+ if ((msg2 = other_hostkeys_message(host, ip, host_key,
+ user_hostfiles, num_user_hostfiles,
+ system_hostfiles, num_system_hostfiles)) != NULL)
+ xextendf(&msg1, "\n", "%s", msg2);
+
+ xextendf(&msg1, "\n",
"Are you sure you want to continue connecting "
- "(yes/no/[fingerprint])? ",
- host, ip, msg1, type, fp,
- options.visual_host_key ? "\n" : "",
- options.visual_host_key ? ra : "",
- msg2);
+ "(yes/no/[fingerprint])? ");
+
+ confirmed = confirm(msg1, fp);
free(ra);
- confirmed = confirm(msg, fp);
free(fp);
+ free(msg1);
+ free(msg2);
if (!confirmed)
goto fail;
hostkey_trusted = 1; /* user explicitly confirmed */
@@ -1009,8 +1277,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
*/
if (options.strict_host_key_checking !=
SSH_STRICT_HOSTKEY_OFF) {
- error("%s host key for %.200s has changed and you have "
- "requested strict checking.", type, host);
+ error("Host key for %.200s has changed and you have "
+ "requested strict checking.", host);
goto fail;
}
@@ -1030,13 +1298,6 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
error("Keyboard-interactive authentication is disabled"
" to avoid man-in-the-middle attacks.");
options.kbd_interactive_authentication = 0;
- options.challenge_response_authentication = 0;
- cancelled_forwarding = 1;
- }
- if (options.challenge_response_authentication) {
- error("Challenge/response authentication is disabled"
- " to avoid man-in-the-middle attacks.");
- options.challenge_response_authentication = 0;
cancelled_forwarding = 1;
}
if (options.forward_agent) {
@@ -1065,6 +1326,11 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
options.tun_open = SSH_TUNMODE_NO;
cancelled_forwarding = 1;
}
+ if (options.update_hostkeys != 0) {
+ error("UpdateHostkeys is disabled because the host "
+ "key is not trusted.");
+ options.update_hostkeys = 0;
+ }
if (options.exit_on_forward_failure && cancelled_forwarding)
fatal("Error: forwarding disabled due to host key "
"check failure");
@@ -1073,7 +1339,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
* XXX Should permit the user to change to use the new id.
* This could be done by converting the host key to an
* identifying sentence, tell that the host identifies itself
- * by that sentence, and ask the user if he/she wishes to
+ * by that sentence, and ask the user if they wish to
* accept the authentication.
*/
break;
@@ -1112,8 +1378,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
}
if (!hostkey_trusted && options.update_hostkeys) {
- debug("%s: hostkey not known or explicitly trusted: "
- "disabling UpdateHostkeys", __func__);
+ debug_f("hostkey not known or explicitly trusted: "
+ "disabling UpdateHostkeys");
options.update_hostkeys = 0;
}
@@ -1133,10 +1399,9 @@ fail:
*/
debug("No matching CA found. Retry with plain key");
if ((r = sshkey_from_private(host_key, &raw_key)) != 0)
- fatal("%s: sshkey_from_private: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "decode key");
if ((r = sshkey_drop_cert(raw_key)) != 0)
- fatal("Couldn't drop certificate: %s", ssh_err(r));
+ fatal_r(r, "Couldn't drop certificate");
host_key = raw_key;
goto retry;
}
@@ -1152,7 +1417,8 @@ fail:
/* returns 0 if key verifies or -1 if key does NOT verify */
int
-verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key)
+verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key,
+ const struct ssh_conn_info *cinfo)
{
u_int i;
int r = -1, flags = 0;
@@ -1161,7 +1427,7 @@ verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key)
if ((fp = sshkey_fingerprint(host_key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
- error("%s: fingerprint host key: %s", __func__, ssh_err(r));
+ error_fr(r, "fingerprint host key");
r = -1;
goto out;
}
@@ -1169,8 +1435,7 @@ verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key)
if (sshkey_is_cert(host_key)) {
if ((cafp = sshkey_fingerprint(host_key->cert->signature_key,
options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL) {
- error("%s: fingerprint CA key: %s",
- __func__, ssh_err(r));
+ error_fr(r, "fingerprint CA key");
r = -1;
goto out;
}
@@ -1192,8 +1457,8 @@ verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key)
}
if (sshkey_equal(previous_host_key, host_key)) {
- debug2("%s: server host key %s %s matches cached key",
- __func__, sshkey_type(host_key), fp);
+ debug2_f("server host key %s %s matches cached key",
+ sshkey_type(host_key), fp);
r = 0;
goto out;
}
@@ -1211,9 +1476,9 @@ verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key)
r = -1;
goto out;
default:
- error("Error checking host key %s %s in "
- "revoked keys file %s: %s", sshkey_type(host_key),
- fp, options.revoked_host_keys, ssh_err(r));
+ error_r(r, "Error checking host key %s %s in "
+ "revoked keys file %s", sshkey_type(host_key),
+ fp, options.revoked_host_keys);
r = -1;
goto out;
}
@@ -1247,9 +1512,10 @@ verify_host_key(char *host, struct sockaddr *hostaddr, struct sshkey *host_key)
}
}
}
- r = check_host_key(host, hostaddr, options.port, host_key, RDRW,
- options.user_hostfiles, options.num_user_hostfiles,
- options.system_hostfiles, options.num_system_hostfiles);
+ r = check_host_key(host, cinfo, hostaddr, options.port, host_key,
+ RDRW, 0, options.user_hostfiles, options.num_user_hostfiles,
+ options.system_hostfiles, options.num_system_hostfiles,
+ options.known_hosts_command);
out:
sshkey_free(plain);
@@ -1272,7 +1538,8 @@ out:
*/
void
ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost,
- struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms)
+ struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms,
+ const struct ssh_conn_info *cinfo)
{
char *host;
char *server_user, *local_user;
@@ -1295,7 +1562,7 @@ ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost,
/* key exchange */
/* authenticate user */
debug("Authenticating to %s:%d as '%s'", host, port, server_user);
- ssh_kex2(ssh, host, hostaddr, port);
+ ssh_kex2(ssh, host, hostaddr, port, cinfo);
ssh_userauth2(ssh, local_user, server_user, host, sensitive);
free(local_user);
free(host);
@@ -1320,14 +1587,15 @@ show_other_keys(struct hostkeys *hostkeys, struct sshkey *key)
for (i = 0; type[i] != -1; i++) {
if (type[i] == key->type)
continue;
- if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found))
+ if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i],
+ -1, &found))
continue;
fp = sshkey_fingerprint(found->key,
options.fingerprint_hash, SSH_FP_DEFAULT);
ra = sshkey_fingerprint(found->key,
options.fingerprint_hash, SSH_FP_RANDOMART);
if (fp == NULL || ra == NULL)
- fatal("%s: sshkey_fingerprint fail", __func__);
+ fatal_f("sshkey_fingerprint fail");
logit("WARNING: %s key found for host %s\n"
"in %s:%lu\n"
"%s key fingerprint %s.",
@@ -1351,7 +1619,7 @@ warn_changed_key(struct sshkey *host_key)
fp = sshkey_fingerprint(host_key, options.fingerprint_hash,
SSH_FP_DEFAULT);
if (fp == NULL)
- fatal("%s: sshkey_fingerprint fail", __func__);
+ fatal_f("sshkey_fingerprint fail");
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");
@@ -1430,7 +1698,8 @@ maybe_add_key_to_agent(const char *authfile, struct sshkey *private,
if (sshkey_is_sk(private))
skprovider = options.sk_provider;
if ((r = ssh_add_identity_constrained(auth_sock, private,
- comment == NULL ? authfile : comment, 0,
+ comment == NULL ? authfile : comment,
+ options.add_keys_to_agent_lifespan,
(options.add_keys_to_agent == 3), 0, skprovider)) == 0)
debug("identity added to agent: %s", authfile);
else
diff --git a/sshconnect.h b/sshconnect.h
index 7c091e2b1..f518a9a13 100644
--- a/sshconnect.h
+++ b/sshconnect.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect.h,v 1.40 2020/01/25 07:17:18 djm Exp $ */
+/* $OpenBSD: sshconnect.h,v 1.46 2020/12/22 00:15:23 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -30,23 +30,56 @@ struct Sensitive {
int nkeys;
};
+struct ssh_conn_info {
+ char *conn_hash_hex;
+ char *shorthost;
+ char *uidstr;
+ char *keyalias;
+ char *thishost;
+ char *host_arg;
+ char *portstr;
+ char *remhost;
+ char *remuser;
+ char *homedir;
+ char *locuser;
+};
+
struct addrinfo;
struct ssh;
+struct hostkeys;
+struct ssh_conn_info;
+
+/* default argument for client percent expansions */
+#define DEFAULT_CLIENT_PERCENT_EXPAND_ARGS(conn_info) \
+ "C", conn_info->conn_hash_hex, \
+ "L", conn_info->shorthost, \
+ "i", conn_info->uidstr, \
+ "k", conn_info->keyalias, \
+ "l", conn_info->thishost, \
+ "n", conn_info->host_arg, \
+ "p", conn_info->portstr, \
+ "d", conn_info->homedir, \
+ "h", conn_info->remhost, \
+ "r", conn_info->remuser, \
+ "u", conn_info->locuser
int ssh_connect(struct ssh *, const char *, const char *,
struct addrinfo *, struct sockaddr_storage *, u_short,
- int, int, int *, int);
+ int, int *, int);
void ssh_kill_proxy_command(void);
void ssh_login(struct ssh *, Sensitive *, const char *,
- struct sockaddr *, u_short, struct passwd *, int);
+ struct sockaddr *, u_short, struct passwd *, int,
+ const struct ssh_conn_info *);
-int verify_host_key(char *, struct sockaddr *, struct sshkey *);
+int verify_host_key(char *, struct sockaddr *, struct sshkey *,
+ const struct ssh_conn_info *);
void get_hostfile_hostname_ipaddr(char *, struct sockaddr *, u_short,
char **, char **);
-void ssh_kex2(struct ssh *ssh, char *, struct sockaddr *, u_short);
+void ssh_kex2(struct ssh *ssh, char *, struct sockaddr *, u_short,
+ const struct ssh_conn_info *);
void ssh_userauth2(struct ssh *ssh, const char *, const char *,
char *, Sensitive *);
@@ -55,3 +88,7 @@ int ssh_local_cmd(const char *);
void maybe_add_key_to_agent(const char *, struct sshkey *,
const char *, const char *);
+
+void load_hostkeys_command(struct hostkeys *, const char *,
+ const char *, const struct ssh_conn_info *,
+ const struct sshkey *, const char *);
diff --git a/sshconnect2.c b/sshconnect2.c
index 1a6545edf..fea50fab6 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect2.c,v 1.321 2020/04/17 03:38:47 djm Exp $ */
+/* $OpenBSD: sshconnect2.c,v 1.351 2021/07/23 05:24:02 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -33,6 +33,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <netdb.h>
#include <pwd.h>
#include <signal.h>
@@ -88,26 +89,39 @@ extern Options options;
* SSH2 key exchange
*/
-u_char *session_id2 = NULL;
-u_int session_id2_len = 0;
-
-char *xxx_host;
-struct sockaddr *xxx_hostaddr;
+static char *xxx_host;
+static struct sockaddr *xxx_hostaddr;
+static const struct ssh_conn_info *xxx_conn_info;
static int
verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh)
{
- if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1)
+ if (verify_host_key(xxx_host, xxx_hostaddr, hostkey,
+ xxx_conn_info) == -1)
fatal("Host key verification failed.");
return 0;
}
+/* Returns the first item from a comma-separated algorithm list */
static char *
-order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
+first_alg(const char *algs)
{
- char *oavail, *avail, *first, *last, *alg, *hostname, *ret;
+ char *ret, *cp;
+
+ ret = xstrdup(algs);
+ if ((cp = strchr(ret, ',')) != NULL)
+ *cp = '\0';
+ return ret;
+}
+
+static char *
+order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port,
+ const struct ssh_conn_info *cinfo)
+{
+ char *oavail = NULL, *avail = NULL, *first = NULL, *last = NULL;
+ char *alg = NULL, *hostname = NULL, *ret = NULL, *best = NULL;
size_t maxlen;
- struct hostkeys *hostkeys;
+ struct hostkeys *hostkeys = NULL;
int ktype;
u_int i;
@@ -115,10 +129,36 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
get_hostfile_hostname_ipaddr(host, hostaddr, port, &hostname, NULL);
hostkeys = init_hostkeys();
for (i = 0; i < options.num_user_hostfiles; i++)
- load_hostkeys(hostkeys, hostname, options.user_hostfiles[i]);
- for (i = 0; i < options.num_system_hostfiles; i++)
- load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]);
+ load_hostkeys(hostkeys, hostname, options.user_hostfiles[i], 0);
+ for (i = 0; i < options.num_system_hostfiles; i++) {
+ load_hostkeys(hostkeys, hostname,
+ options.system_hostfiles[i], 0);
+ }
+ if (options.known_hosts_command != NULL) {
+ load_hostkeys_command(hostkeys, options.known_hosts_command,
+ "ORDER", cinfo, NULL, host);
+ }
+ /*
+ * If a plain public key exists that matches the type of the best
+ * preference HostkeyAlgorithms, then use the whole list as is.
+ * Note that we ignore whether the best preference algorithm is a
+ * certificate type, as sshconnect.c will downgrade certs to
+ * plain keys if necessary.
+ */
+ best = first_alg(options.hostkeyalgorithms);
+ if (lookup_key_in_hostkeys_by_type(hostkeys,
+ sshkey_type_plain(sshkey_type_from_name(best)),
+ sshkey_ecdsa_nid_from_name(best), NULL)) {
+ debug3_f("have matching best-preference key type %s, "
+ "using HostkeyAlgorithms verbatim", best);
+ ret = xstrdup(options.hostkeyalgorithms);
+ goto out;
+ }
+ /*
+ * Otherwise, prefer the host key algorithms that match known keys
+ * while keeping the ordering of HostkeyAlgorithms as much as possible.
+ */
oavail = avail = xstrdup(options.hostkeyalgorithms);
maxlen = strlen(avail) + 1;
first = xmalloc(maxlen);
@@ -134,19 +174,35 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
while ((alg = strsep(&avail, ",")) && *alg != '\0') {
if ((ktype = sshkey_type_from_name(alg)) == KEY_UNSPEC)
- fatal("%s: unknown alg %s", __func__, alg);
+ fatal_f("unknown alg %s", alg);
+ /*
+ * If we have a @cert-authority marker in known_hosts then
+ * prefer all certificate algorithms.
+ */
+ if (sshkey_type_is_cert(ktype) &&
+ lookup_marker_in_hostkeys(hostkeys, MRK_CA)) {
+ ALG_APPEND(first, alg);
+ continue;
+ }
+ /* If the key appears in known_hosts then prefer it */
if (lookup_key_in_hostkeys_by_type(hostkeys,
- sshkey_type_plain(ktype), NULL))
+ sshkey_type_plain(ktype),
+ sshkey_ecdsa_nid_from_name(alg), NULL)) {
ALG_APPEND(first, alg);
- else
- ALG_APPEND(last, alg);
+ continue;
+ }
+ /* Otherwise, put it last */
+ ALG_APPEND(last, alg);
}
#undef ALG_APPEND
xasprintf(&ret, "%s%s%s", first,
(*first == '\0' || *last == '\0') ? "" : ",", last);
if (*first != '\0')
- debug3("%s: prefer hostkeyalgs: %s", __func__, first);
-
+ debug3_f("prefer hostkeyalgs: %s", first);
+ else
+ debug3_f("no algorithms matched; accept original");
+ out:
+ free(best);
free(first);
free(last);
free(hostname);
@@ -157,7 +213,8 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
}
void
-ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
+ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port,
+ const struct ssh_conn_info *cinfo)
{
char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
char *s, *all_key;
@@ -165,6 +222,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
xxx_host = host;
xxx_hostaddr = hostaddr;
+ xxx_conn_info = cinfo;
/*
* If the user has not specified HostkeyAlgorithms, or has only
@@ -178,18 +236,18 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
/* Expand or fill in HostkeyAlgorithms */
all_key = sshkey_alg_list(0, 0, 1, ',');
- if (kex_assemble_names(&options.hostkeyalgorithms,
- kex_default_pk_alg(), all_key) != 0)
- fatal("%s: kex_assemble_namelist", __func__);
+ if ((r = kex_assemble_names(&options.hostkeyalgorithms,
+ kex_default_pk_alg(), all_key)) != 0)
+ fatal_fr(r, "kex_assemble_namelist");
free(all_key);
if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL)
- fatal("%s: kex_names_cat", __func__);
- myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(s);
+ fatal_f("kex_names_cat");
+ myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(ssh, s);
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
- compat_cipher_proposal(options.ciphers);
+ compat_cipher_proposal(ssh, options.ciphers);
myproposal[PROPOSAL_ENC_ALGS_STOC] =
- compat_cipher_proposal(options.ciphers);
+ compat_cipher_proposal(ssh, options.ciphers);
myproposal[PROPOSAL_COMP_ALGS_CTOS] =
myproposal[PROPOSAL_COMP_ALGS_STOC] =
(char *)compression_alg_list(options.compression);
@@ -198,12 +256,12 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
if (use_known_hosts_order) {
/* Query known_hosts and prefer algorithms that appear there */
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
- compat_pkalg_proposal(
- order_hostkeyalgs(host, hostaddr, port));
+ compat_pkalg_proposal(ssh,
+ order_hostkeyalgs(host, hostaddr, port, cinfo));
} else {
/* Use specified HostkeyAlgorithms exactly */
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
- compat_pkalg_proposal(options.hostkeyalgorithms);
+ compat_pkalg_proposal(ssh, options.hostkeyalgorithms);
}
if (options.rekey_limit || options.rekey_interval)
@@ -212,7 +270,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
/* start key exchange */
if ((r = kex_setup(ssh, myproposal)) != 0)
- fatal("kex_setup: %s", ssh_err(r));
+ fatal_r(r, "kex_setup");
#ifdef WITH_OPENSSL
ssh->kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_client;
ssh->kex->kex[KEX_DH_GRP14_SHA1] = kex_gen_client;
@@ -226,19 +284,16 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
# endif
#endif
ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client;
- ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client;
+ ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client;
ssh->kex->verify_host_key=&verify_host_key_callback;
ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done);
/* remove ext-info from the KEX proposals for rekeying */
myproposal[PROPOSAL_KEX_ALGS] =
- compat_kex_proposal(options.kex_algorithms);
+ compat_kex_proposal(ssh, options.kex_algorithms);
if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0)
- fatal("kex_prop2buf: %s", ssh_err(r));
-
- session_id2 = ssh->kex->session_id;
- session_id2_len = ssh->kex->session_id_len;
+ fatal_r(r, "kex_prop2buf");
#ifdef DEBUG_KEXDH
/* send 1st encrypted/maced/compressed message */
@@ -246,7 +301,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
(r = sshpkt_put_cstring(ssh, "markus")) != 0 ||
(r = sshpkt_send(ssh)) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send packet");
#endif
}
@@ -387,8 +442,6 @@ ssh_userauth2(struct ssh *ssh, const char *local_user,
Authctxt authctxt;
int r;
- if (options.challenge_response_authentication)
- options.kbd_interactive_authentication = 1;
if (options.preferred_authentications == NULL)
options.preferred_authentications = authmethods_get();
@@ -414,14 +467,13 @@ ssh_userauth2(struct ssh *ssh, const char *local_user,
authctxt.agent_fd = -1;
pubkey_prepare(&authctxt);
if (authctxt.method == NULL) {
- fatal("%s: internal error: cannot send userauth none request",
- __func__);
+ fatal_f("internal error: cannot send userauth none request");
}
if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_REQUEST)) != 0 ||
(r = sshpkt_put_cstring(ssh, "ssh-userauth")) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send packet");
ssh->authctxt = &authctxt;
ssh_dispatch_init(ssh, &input_userauth_error);
@@ -435,7 +487,14 @@ ssh_userauth2(struct ssh *ssh, const char *local_user,
if (!authctxt.success)
fatal("Authentication failed.");
- debug("Authentication succeeded (%s).", authctxt.method->name);
+ if (ssh_packet_connection_is_on_socket(ssh)) {
+ verbose("Authenticated to %s ([%s]:%d) using \"%s\".", host,
+ ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
+ authctxt.method->name);
+ } else {
+ verbose("Authenticated to %s (via proxy) using \"%s\".", host,
+ authctxt.method->name);
+ }
}
/* ARGSUSED */
@@ -519,7 +578,7 @@ userauth(struct ssh *ssh, char *authlist)
static int
input_userauth_error(int type, u_int32_t seq, struct ssh *ssh)
{
- fatal("%s: bad message during authentication: type %d", __func__, type);
+ fatal_f("bad message during authentication: type %d", type);
return 0;
}
@@ -531,7 +590,7 @@ input_userauth_banner(int type, u_int32_t seq, struct ssh *ssh)
size_t len;
int r;
- debug3("%s", __func__);
+ debug3_f("entering");
if ((r = sshpkt_get_cstring(ssh, &msg, &len)) != 0 ||
(r = sshpkt_get_cstring(ssh, NULL, NULL)) != 0)
goto out;
@@ -550,7 +609,7 @@ input_userauth_success(int type, u_int32_t seq, struct ssh *ssh)
Authctxt *authctxt = ssh->authctxt;
if (authctxt == NULL)
- fatal("%s: no authentication context", __func__);
+ fatal_f("no authentication context");
free(authctxt->authlist);
authctxt->authlist = NULL;
if (authctxt->method != NULL && authctxt->method->cleanup != NULL)
@@ -568,7 +627,7 @@ input_userauth_success_unexpected(int type, u_int32_t seq, struct ssh *ssh)
Authctxt *authctxt = ssh->authctxt;
if (authctxt == NULL)
- fatal("%s: no authentication context", __func__);
+ fatal_f("no authentication context");
fatal("Unexpected authentication success during %s.",
authctxt->method->name);
@@ -593,7 +652,8 @@ input_userauth_failure(int type, u_int32_t seq, struct ssh *ssh)
goto out;
if (partial != 0) {
- verbose("Authenticated with partial success.");
+ verbose("Authenticated using \"%s\" with partial success.",
+ authctxt->method->name);
/* reset state */
pubkey_reset(authctxt);
}
@@ -617,7 +677,7 @@ format_identity(Identity *id)
const char *note = "";
if (id->key != NULL) {
- fp = sshkey_fingerprint(id->key, options.fingerprint_hash,
+ fp = sshkey_fingerprint(id->key, options.fingerprint_hash,
SSH_FP_DEFAULT);
}
if (id->key) {
@@ -658,11 +718,11 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh)
goto done;
if ((pktype = sshkey_type_from_name(pkalg)) == KEY_UNSPEC) {
- debug("%s: server sent unknown pkalg %s", __func__, pkalg);
+ debug_f("server sent unknown pkalg %s", pkalg);
goto done;
}
if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
- debug("no key from blob. pkalg %s: %s", pkalg, ssh_err(r));
+ debug_r(r, "no key from blob. pkalg %s", pkalg);
goto done;
}
if (key->type != pktype) {
@@ -686,7 +746,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh)
if (!found || id == NULL) {
fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT);
- error("%s: server replied with unknown key: %s %s", __func__,
+ error_f("server replied with unknown key: %s %s",
sshkey_type(key), fp == NULL ? "<ERROR>" : fp);
goto done;
}
@@ -752,7 +812,7 @@ userauth_gssapi(struct ssh *ssh)
(r = sshpkt_put_u8(ssh, mech->length)) != 0 ||
(r = sshpkt_put(ssh, mech->elements, mech->length)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send packet");
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_RESPONSE, &input_gssapi_response);
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token);
@@ -800,7 +860,7 @@ process_gssapi_token(struct ssh *ssh, gss_buffer_t recv_tok)
(r = sshpkt_put_string(ssh, send_tok.value,
send_tok.length)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send %u packet", type);
gss_release_buffer(&ms, &send_tok);
}
@@ -811,17 +871,18 @@ process_gssapi_token(struct ssh *ssh, gss_buffer_t recv_tok)
if ((r = sshpkt_start(ssh,
SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send completion");
} else {
struct sshbuf *b;
if ((b = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
ssh_gssapi_buildmic(b, authctxt->server_user,
- authctxt->service, "gssapi-with-mic");
+ authctxt->service, "gssapi-with-mic",
+ ssh->kex->session_id);
if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL)
- fatal("%s: sshbuf_mutable_ptr failed", __func__);
+ fatal_f("sshbuf_mutable_ptr failed");
gssbuf.length = sshbuf_len(b);
status = ssh_gssapi_sign(gssctxt, &gssbuf, &mic);
@@ -832,7 +893,7 @@ process_gssapi_token(struct ssh *ssh, gss_buffer_t recv_tok)
(r = sshpkt_put_string(ssh, mic.value,
mic.length)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send MIC");
}
sshbuf_free(b);
@@ -990,7 +1051,7 @@ userauth_none(struct ssh *ssh)
(r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send packet");
return 1;
}
@@ -1019,7 +1080,7 @@ userauth_passwd(struct ssh *ssh)
(r = sshpkt_put_cstring(ssh, password)) != 0 ||
(r = sshpkt_add_padding(ssh, 64)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send packet");
free(prompt);
if (password != NULL)
@@ -1120,6 +1181,7 @@ static char *
key_sig_algorithm(struct ssh *ssh, const struct sshkey *key)
{
char *allowed, *oallowed, *cp, *tmp, *alg = NULL;
+ const char *server_sig_algs;
/*
* The signature algorithm will only differ from the key algorithm
@@ -1128,23 +1190,32 @@ key_sig_algorithm(struct ssh *ssh, const struct sshkey *key)
*/
if (ssh == NULL || ssh->kex->server_sig_algs == NULL ||
(key->type != KEY_RSA && key->type != KEY_RSA_CERT) ||
- (key->type == KEY_RSA_CERT && (datafellows & SSH_BUG_SIGTYPE))) {
+ (key->type == KEY_RSA_CERT && (ssh->compat & SSH_BUG_SIGTYPE))) {
/* Filter base key signature alg against our configuration */
return match_list(sshkey_ssh_name(key),
- options.pubkey_key_types, NULL);
+ options.pubkey_accepted_algos, NULL);
}
/*
+ * Workaround OpenSSH 7.4 bug: this version supports RSA/SHA-2 but
+ * fails to advertise it via SSH2_MSG_EXT_INFO.
+ */
+ server_sig_algs = ssh->kex->server_sig_algs;
+ if (key->type == KEY_RSA && (ssh->compat & SSH_BUG_SIGTYPE74))
+ server_sig_algs = "rsa-sha2-256,rsa-sha2-512";
+
+ /*
* For RSA keys/certs, since these might have a different sig type:
- * find the first entry in PubkeyAcceptedKeyTypes of the right type
+ * find the first entry in PubkeyAcceptedAlgorithms of the right type
* that also appears in the supported signature algorithms list from
* the server.
*/
- oallowed = allowed = xstrdup(options.pubkey_key_types);
+ oallowed = allowed = xstrdup(options.pubkey_accepted_algos);
while ((cp = strsep(&allowed, ",")) != NULL) {
if (sshkey_type_from_name(cp) != key->type)
continue;
- tmp = match_list(sshkey_sigalg_by_name(cp), ssh->kex->server_sig_algs, NULL);
+ tmp = match_list(sshkey_sigalg_by_name(cp),
+ server_sig_algs, NULL);
if (tmp != NULL)
alg = xstrdup(cp);
free(tmp);
@@ -1160,9 +1231,9 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen, u_int compat, const char *alg)
{
struct sshkey *sign_key = NULL, *prv = NULL;
- int r = SSH_ERR_INTERNAL_ERROR;
+ int retried = 0, r = SSH_ERR_INTERNAL_ERROR;
struct notifier_ctx *notifier = NULL;
- char *fp = NULL;
+ char *fp = NULL, *pin = NULL, *prompt = NULL;
*sigp = NULL;
*lenp = 0;
@@ -1185,41 +1256,61 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
if ((prv = load_identity_file(id)) == NULL)
return SSH_ERR_KEY_NOT_FOUND;
if (id->key != NULL && !sshkey_equal_public(prv, id->key)) {
- error("%s: private key %s contents do not match public",
- __func__, id->filename);
+ error_f("private key %s contents do not match public",
+ id->filename);
r = SSH_ERR_KEY_NOT_FOUND;
goto out;
}
sign_key = prv;
- if (sshkey_is_sk(sign_key) &&
- (sign_key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
- /* XXX match batch mode should just skip these keys? */
- if ((fp = sshkey_fingerprint(sign_key,
- options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
- fatal("%s: sshkey_fingerprint", __func__);
- notifier = notify_start(options.batch_mode,
- "Confirm user presence for key %s %s",
- sshkey_type(sign_key), fp);
- free(fp);
+ if (sshkey_is_sk(sign_key)) {
+ if ((sign_key->sk_flags &
+ SSH_SK_USER_VERIFICATION_REQD)) {
+ retry_pin:
+ xasprintf(&prompt, "Enter PIN for %s key %s: ",
+ sshkey_type(sign_key), id->filename);
+ pin = read_passphrase(prompt, 0);
+ }
+ if ((sign_key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
+ /* XXX should batch mode just skip these? */
+ if ((fp = sshkey_fingerprint(sign_key,
+ options.fingerprint_hash,
+ SSH_FP_DEFAULT)) == NULL)
+ fatal_f("fingerprint failed");
+ notifier = notify_start(options.batch_mode,
+ "Confirm user presence for key %s %s",
+ sshkey_type(sign_key), fp);
+ free(fp);
+ }
}
}
if ((r = sshkey_sign(sign_key, sigp, lenp, data, datalen,
- alg, options.sk_provider, compat)) != 0) {
- debug("%s: sshkey_sign: %s", __func__, ssh_err(r));
+ alg, options.sk_provider, pin, compat)) != 0) {
+ debug_fr(r, "sshkey_sign");
+ if (pin == NULL && !retried && sshkey_is_sk(sign_key) &&
+ r == SSH_ERR_KEY_WRONG_PASSPHRASE) {
+ notify_complete(notifier, NULL);
+ notifier = NULL;
+ retried = 1;
+ goto retry_pin;
+ }
goto out;
}
+
/*
* PKCS#11 tokens may not support all signature algorithms,
* so check what we get back.
*/
if ((r = sshkey_check_sigtype(*sigp, *lenp, alg)) != 0) {
- debug("%s: sshkey_check_sigtype: %s", __func__, ssh_err(r));
+ debug_fr(r, "sshkey_check_sigtype");
goto out;
}
/* success */
r = 0;
out:
- notify_complete(notifier);
+ free(prompt);
+ if (pin != NULL)
+ freezero(pin, strlen(pin));
+ notify_complete(notifier, r == 0 ? "User presence confirmed" : NULL);
sshkey_free(prv);
return r;
}
@@ -1259,7 +1350,7 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id)
SSH_FP_DEFAULT)) == NULL)
return 0;
- debug3("%s: %s %s", __func__, sshkey_type(id->key), fp);
+ debug3_f("%s %s", sshkey_type(id->key), fp);
/*
* If the key is an certificate, try to find a matching private key
@@ -1296,12 +1387,12 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id)
}
}
if (sign_id != NULL) {
- debug2("%s: using private key \"%s\"%s for "
- "certificate", __func__, id->filename,
- id->agent_fd != -1 ? " from agent" : "");
+ debug2_f("using private key \"%s\"%s for "
+ "certificate", sign_id->filename,
+ sign_id->agent_fd != -1 ? " from agent" : "");
} else {
- debug("%s: no separate private key for certificate "
- "\"%s\"", __func__, id->filename);
+ debug_f("no separate private key for certificate "
+ "\"%s\"", id->filename);
}
}
@@ -1319,26 +1410,21 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id)
signature = NULL;
if ((alg = key_sig_algorithm(fallback_sigtype ? NULL : ssh,
id->key)) == NULL) {
- error("%s: no mutual signature supported", __func__);
+ error_f("no mutual signature supported");
goto out;
}
- debug3("%s: signing using %s %s", __func__, alg, fp);
+ debug3_f("signing using %s %s", alg, fp);
sshbuf_free(b);
if ((b = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
- if (datafellows & SSH_OLD_SESSIONID) {
- if ((r = sshbuf_put(b, session_id2,
- session_id2_len)) != 0) {
- fatal("%s: sshbuf_put: %s",
- __func__, ssh_err(r));
- }
+ fatal_f("sshbuf_new failed");
+ if (ssh->compat & SSH_OLD_SESSIONID) {
+ if ((r = sshbuf_putb(b, ssh->kex->session_id)) != 0)
+ fatal_fr(r, "sshbuf_putb");
} else {
- if ((r = sshbuf_put_string(b, session_id2,
- session_id2_len)) != 0) {
- fatal("%s: sshbuf_put_string: %s",
- __func__, ssh_err(r));
- }
+ if ((r = sshbuf_put_stringb(b,
+ ssh->kex->session_id)) != 0)
+ fatal_fr(r, "sshbuf_put_stringb");
}
skip = sshbuf_len(b);
if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
@@ -1348,13 +1434,12 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id)
(r = sshbuf_put_u8(b, 1)) != 0 ||
(r = sshbuf_put_cstring(b, alg)) != 0 ||
(r = sshkey_puts(id->key, b)) != 0) {
- fatal("%s: assemble signed data: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "assemble signed data");
}
/* generate signature */
r = identity_sign(sign_id, &signature, &slen,
- sshbuf_ptr(b), sshbuf_len(b), datafellows, alg);
+ sshbuf_ptr(b), sshbuf_len(b), ssh->compat, alg);
if (r == 0)
break;
else if (r == SSH_ERR_KEY_NOT_FOUND)
@@ -1369,30 +1454,30 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id)
loc, sshkey_type(id->key), fp);
continue;
}
- error("%s: signing failed for %s \"%s\"%s: %s", __func__,
+ error_fr(r, "signing failed for %s \"%s\"%s",
sshkey_type(sign_id->key), sign_id->filename,
- id->agent_fd != -1 ? " from agent" : "", ssh_err(r));
+ id->agent_fd != -1 ? " from agent" : "");
goto out;
}
if (slen == 0 || signature == NULL) /* shouldn't happen */
- fatal("%s: no signature", __func__);
+ fatal_f("no signature");
/* append signature */
if ((r = sshbuf_put_string(b, signature, slen)) != 0)
- fatal("%s: append signature: %s", __func__, ssh_err(r));
+ fatal_fr(r, "append signature");
#ifdef DEBUG_PK
sshbuf_dump(b, stderr);
#endif
/* skip session id and packet type */
if ((r = sshbuf_consume(b, skip + 1)) != 0)
- fatal("%s: consume: %s", __func__, ssh_err(r));
+ fatal_fr(r, "consume");
/* put remaining data from buffer into packet */
if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
(r = sshpkt_putb(ssh, b)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: enqueue request: %s", __func__, ssh_err(r));
+ fatal_fr(r, "enqueue request");
/* success */
sent = 1;
@@ -1416,13 +1501,13 @@ send_pubkey_test(struct ssh *ssh, Identity *id)
int sent = 0, r;
if ((alg = key_sig_algorithm(ssh, id->key)) == NULL) {
- debug("%s: no mutual signature algorithm", __func__);
+ debug_f("no mutual signature algorithm");
goto out;
}
if ((r = sshkey_to_blob(id->key, &blob, &bloblen)) != 0) {
/* we cannot handle this key */
- debug3("%s: cannot handle key", __func__);
+ debug3_f("cannot handle key");
goto out;
}
/* register callback for USERAUTH_PK_OK message */
@@ -1436,7 +1521,7 @@ send_pubkey_test(struct ssh *ssh, Identity *id)
(r = sshpkt_put_cstring(ssh, alg)) != 0 ||
(r = sshpkt_put_string(ssh, blob, bloblen)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send packet");
sent = 1;
out:
@@ -1454,8 +1539,9 @@ load_identity_file(Identity *id)
struct stat st;
if (stat(id->filename, &st) == -1) {
- (id->userprovided ? logit : debug3)("no such identity: %s: %s",
- id->filename, strerror(errno));
+ do_log2(id->userprovided ?
+ SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_DEBUG3,
+ "no such identity: %s: %s", id->filename, strerror(errno));
return NULL;
}
snprintf(prompt, sizeof prompt,
@@ -1485,14 +1571,13 @@ load_identity_file(Identity *id)
break;
case SSH_ERR_SYSTEM_ERROR:
if (errno == ENOENT) {
- debug2("Load key \"%s\": %s",
- id->filename, ssh_err(r));
+ debug2_r(r, "Load key \"%s\"", id->filename);
quit = 1;
break;
}
/* FALLTHROUGH */
default:
- error("Load key \"%s\": %s", id->filename, ssh_err(r));
+ error_r(r, "Load key \"%s\"", id->filename);
quit = 1;
break;
}
@@ -1521,25 +1606,25 @@ static int
key_type_allowed_by_config(struct sshkey *key)
{
if (match_pattern_list(sshkey_ssh_name(key),
- options.pubkey_key_types, 0) == 1)
+ options.pubkey_accepted_algos, 0) == 1)
return 1;
/* RSA keys/certs might be allowed by alternate signature types */
switch (key->type) {
case KEY_RSA:
if (match_pattern_list("rsa-sha2-512",
- options.pubkey_key_types, 0) == 1)
+ options.pubkey_accepted_algos, 0) == 1)
return 1;
if (match_pattern_list("rsa-sha2-256",
- options.pubkey_key_types, 0) == 1)
+ options.pubkey_accepted_algos, 0) == 1)
return 1;
break;
case KEY_RSA_CERT:
if (match_pattern_list("rsa-sha2-512-cert-v01@openssh.com",
- options.pubkey_key_types, 0) == 1)
+ options.pubkey_accepted_algos, 0) == 1)
return 1;
if (match_pattern_list("rsa-sha2-256-cert-v01@openssh.com",
- options.pubkey_key_types, 0) == 1)
+ options.pubkey_accepted_algos, 0) == 1)
return 1;
break;
}
@@ -1549,8 +1634,8 @@ key_type_allowed_by_config(struct sshkey *key)
/*
* try keys in the following order:
- * 1. certificates listed in the config file
- * 2. other input certificates
+ * 1. certificates listed in the config file
+ * 2. other input certificates
* 3. agent keys that are found in the config file
* 4. other agent keys
* 5. keys that are only listed in the config file
@@ -1576,15 +1661,14 @@ pubkey_prepare(Authctxt *authctxt)
key = options.identity_keys[i];
if (key && key->cert &&
key->cert->type != SSH2_CERT_TYPE_USER) {
- debug("%s: ignoring certificate %s: not a user "
- "certificate", __func__,
- options.identity_files[i]);
+ debug_f("ignoring certificate %s: not a user "
+ "certificate", options.identity_files[i]);
continue;
}
if (key && sshkey_is_sk(key) && options.sk_provider == NULL) {
- debug("%s: ignoring authenticator-hosted key %s as no "
+ debug_f("ignoring authenticator-hosted key %s as no "
"SecurityKeyProvider has been specified",
- __func__, options.identity_files[i]);
+ options.identity_files[i]);
continue;
}
options.identity_keys[i] = NULL;
@@ -1600,16 +1684,15 @@ pubkey_prepare(Authctxt *authctxt)
key = options.certificates[i];
if (!sshkey_is_cert(key) || key->cert == NULL ||
key->cert->type != SSH2_CERT_TYPE_USER) {
- debug("%s: ignoring certificate %s: not a user "
- "certificate", __func__,
- options.identity_files[i]);
+ debug_f("ignoring certificate %s: not a user "
+ "certificate", options.identity_files[i]);
continue;
}
if (key && sshkey_is_sk(key) && options.sk_provider == NULL) {
- debug("%s: ignoring authenticator-hosted key "
+ debug_f("ignoring authenticator-hosted key "
"certificate %s as no "
"SecurityKeyProvider has been specified",
- __func__, options.identity_files[i]);
+ options.identity_files[i]);
continue;
}
id = xcalloc(1, sizeof(*id));
@@ -1622,12 +1705,10 @@ pubkey_prepare(Authctxt *authctxt)
/* list of keys supported by the agent */
if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) {
if (r != SSH_ERR_AGENT_NOT_PRESENT)
- debug("%s: ssh_get_authentication_socket: %s",
- __func__, ssh_err(r));
+ debug_fr(r, "ssh_get_authentication_socket");
} else if ((r = ssh_fetch_identitylist(agent_fd, &idlist)) != 0) {
if (r != SSH_ERR_AGENT_NO_IDENTITIES)
- debug("%s: ssh_fetch_identitylist: %s",
- __func__, ssh_err(r));
+ debug_fr(r, "ssh_fetch_identitylist");
close(agent_fd);
} else {
for (j = 0; j < idlist->nkeys; j++) {
@@ -1658,10 +1739,7 @@ pubkey_prepare(Authctxt *authctxt)
}
ssh_free_identitylist(idlist);
/* append remaining agent keys */
- for (id = TAILQ_FIRST(&agent); id; id = TAILQ_FIRST(&agent)) {
- TAILQ_REMOVE(&agent, id, next);
- TAILQ_INSERT_TAIL(preferred, id, next);
- }
+ TAILQ_CONCAT(preferred, &agent, next);
authctxt->agent_fd = agent_fd;
}
/* Prefer PKCS11 keys that are explicitly listed */
@@ -1687,15 +1765,12 @@ pubkey_prepare(Authctxt *authctxt)
}
}
/* append remaining keys from the config file */
- for (id = TAILQ_FIRST(&files); id; id = TAILQ_FIRST(&files)) {
- TAILQ_REMOVE(&files, id, next);
- TAILQ_INSERT_TAIL(preferred, id, next);
- }
- /* finally, filter by PubkeyAcceptedKeyTypes */
+ TAILQ_CONCAT(preferred, &files, next);
+ /* finally, filter by PubkeyAcceptedAlgorithms */
TAILQ_FOREACH_SAFE(id, preferred, next, id2) {
if (id->key != NULL && !key_type_allowed_by_config(id->key)) {
debug("Skipping %s key %s - "
- "not in PubkeyAcceptedKeyTypes",
+ "corresponding algo not in PubkeyAcceptedAlgorithms",
sshkey_ssh_name(id->key), id->filename);
TAILQ_REMOVE(preferred, id, next);
sshkey_free(id->key);
@@ -1710,7 +1785,7 @@ pubkey_prepare(Authctxt *authctxt)
debug("Will attempt key: %s", ident);
free(ident);
}
- debug2("%s: done", __func__);
+ debug2_f("done");
}
static void
@@ -1742,12 +1817,12 @@ pubkey_reset(Authctxt *authctxt)
}
static int
-try_identity(Identity *id)
+try_identity(struct ssh *ssh, Identity *id)
{
if (!id->key)
return (0);
if (sshkey_type_plain(id->key->type) == KEY_RSA &&
- (datafellows & SSH_BUG_RSASIGMD5) != 0) {
+ (ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
debug("Skipped %s key %s for RSA/MD5 server",
sshkey_type(id->key), id->filename);
return (0);
@@ -1775,7 +1850,7 @@ userauth_pubkey(struct ssh *ssh)
* private key instead
*/
if (id->key != NULL) {
- if (try_identity(id)) {
+ if (try_identity(ssh, id)) {
ident = format_identity(id);
debug("Offering public key: %s", ident);
free(ident);
@@ -1785,7 +1860,7 @@ userauth_pubkey(struct ssh *ssh)
debug("Trying private key: %s", id->filename);
id->key = load_identity_file(id);
if (id->key != NULL) {
- if (try_identity(id)) {
+ if (try_identity(ssh, id)) {
id->isprivate = 1;
sent = sign_and_send_pubkey(ssh, id);
}
@@ -1827,7 +1902,7 @@ userauth_kbdint(struct ssh *ssh)
(r = sshpkt_put_cstring(ssh, options.kbd_interactive_devices ?
options.kbd_interactive_devices : "")) != 0 ||
(r = sshpkt_send(ssh)) != 0)
- fatal("%s: %s", __func__, ssh_err(r));
+ fatal_fr(r, "send packet");
ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req);
return 1;
@@ -1841,15 +1916,15 @@ input_userauth_info_req(int type, u_int32_t seq, struct ssh *ssh)
{
Authctxt *authctxt = ssh->authctxt;
char *name = NULL, *inst = NULL, *lang = NULL, *prompt = NULL;
- char *response = NULL;
+ char *display_prompt = NULL, *response = NULL;
u_char echo = 0;
u_int num_prompts, i;
int r;
- debug2("input_userauth_info_req");
+ debug2_f("entering");
if (authctxt == NULL)
- fatal("input_userauth_info_req: no authentication context");
+ fatal_f("no authentication context");
authctxt->info_req_seen = 1;
@@ -1874,17 +1949,22 @@ input_userauth_info_req(int type, u_int32_t seq, struct ssh *ssh)
(r = sshpkt_put_u32(ssh, num_prompts)) != 0)
goto out;
- debug2("input_userauth_info_req: num_prompts %d", num_prompts);
+ debug2_f("num_prompts %d", num_prompts);
for (i = 0; i < num_prompts; i++) {
if ((r = sshpkt_get_cstring(ssh, &prompt, NULL)) != 0 ||
(r = sshpkt_get_u8(ssh, &echo)) != 0)
goto out;
- response = read_passphrase(prompt, echo ? RP_ECHO : 0);
+ if (asmprintf(&display_prompt, INT_MAX, NULL, "(%s@%s) %s",
+ authctxt->server_user, options.host_key_alias ?
+ options.host_key_alias : authctxt->host, prompt) == -1)
+ fatal_f("asmprintf failed");
+ response = read_passphrase(display_prompt, echo ? RP_ECHO : 0);
if ((r = sshpkt_put_cstring(ssh, response)) != 0)
goto out;
freezero(response, strlen(response));
free(prompt);
- response = prompt = NULL;
+ free(display_prompt);
+ display_prompt = response = prompt = NULL;
}
/* done with parsing incoming message. */
if ((r = sshpkt_get_end(ssh)) != 0 ||
@@ -1895,6 +1975,7 @@ input_userauth_info_req(int type, u_int32_t seq, struct ssh *ssh)
if (response)
freezero(response, strlen(response));
free(prompt);
+ free(display_prompt);
free(name);
free(inst);
free(lang);
@@ -1917,46 +1998,46 @@ ssh_keysign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp,
*lenp = 0;
if (stat(_PATH_SSH_KEY_SIGN, &st) == -1) {
- error("%s: not installed: %s", __func__, strerror(errno));
+ error_f("not installed: %s", strerror(errno));
return -1;
}
if (fflush(stdout) != 0) {
- error("%s: fflush: %s", __func__, strerror(errno));
+ error_f("fflush: %s", strerror(errno));
return -1;
}
if (pipe(to) == -1) {
- error("%s: pipe: %s", __func__, strerror(errno));
+ error_f("pipe: %s", strerror(errno));
return -1;
}
if (pipe(from) == -1) {
- error("%s: pipe: %s", __func__, strerror(errno));
+ error_f("pipe: %s", strerror(errno));
return -1;
}
if ((pid = fork()) == -1) {
- error("%s: fork: %s", __func__, strerror(errno));
+ error_f("fork: %s", strerror(errno));
return -1;
}
osigchld = ssh_signal(SIGCHLD, SIG_DFL);
if (pid == 0) {
close(from[0]);
if (dup2(from[1], STDOUT_FILENO) == -1)
- fatal("%s: dup2: %s", __func__, strerror(errno));
+ fatal_f("dup2: %s", strerror(errno));
close(to[1]);
if (dup2(to[0], STDIN_FILENO) == -1)
- fatal("%s: dup2: %s", __func__, strerror(errno));
+ fatal_f("dup2: %s", strerror(errno));
close(from[1]);
close(to[0]);
if (dup2(sock, STDERR_FILENO + 1) == -1)
- fatal("%s: dup2: %s", __func__, strerror(errno));
+ fatal_f("dup2: %s", strerror(errno));
sock = STDERR_FILENO + 1;
fcntl(sock, F_SETFD, 0); /* keep the socket on exec */
closefrom(sock + 1);
- debug3("%s: [child] pid=%ld, exec %s",
- __func__, (long)getpid(), _PATH_SSH_KEY_SIGN);
+ debug3_f("[child] pid=%ld, exec %s",
+ (long)getpid(), _PATH_SSH_KEY_SIGN);
execl(_PATH_SSH_KEY_SIGN, _PATH_SSH_KEY_SIGN, (char *)NULL);
- fatal("%s: exec(%s): %s", __func__, _PATH_SSH_KEY_SIGN,
+ fatal_f("exec(%s): %s", _PATH_SSH_KEY_SIGN,
strerror(errno));
}
close(from[1]);
@@ -1964,49 +2045,47 @@ ssh_keysign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp,
sock = STDERR_FILENO + 1;
if ((b = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
/* send # of sock, data to be signed */
if ((r = sshbuf_put_u32(b, sock)) != 0 ||
(r = sshbuf_put_string(b, data, datalen)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "buffer error");
if (ssh_msg_send(to[1], version, b) == -1)
- fatal("%s: couldn't send request", __func__);
+ fatal_f("couldn't send request");
sshbuf_reset(b);
r = ssh_msg_recv(from[0], b);
close(from[0]);
close(to[1]);
if (r < 0) {
- error("%s: no reply", __func__);
+ error_f("no reply");
goto fail;
}
errno = 0;
while (waitpid(pid, &status, 0) == -1) {
if (errno != EINTR) {
- error("%s: waitpid %ld: %s",
- __func__, (long)pid, strerror(errno));
+ error_f("waitpid %ld: %s", (long)pid, strerror(errno));
goto fail;
}
}
if (!WIFEXITED(status)) {
- error("%s: exited abnormally", __func__);
+ error_f("exited abnormally");
goto fail;
}
if (WEXITSTATUS(status) != 0) {
- error("%s: exited with status %d",
- __func__, WEXITSTATUS(status));
+ error_f("exited with status %d", WEXITSTATUS(status));
goto fail;
}
if ((r = sshbuf_get_u8(b, &rversion)) != 0) {
- error("%s: buffer error: %s", __func__, ssh_err(r));
+ error_fr(r, "buffer error");
goto fail;
}
if (rversion != version) {
- error("%s: bad version", __func__);
+ error_f("bad version");
goto fail;
}
if ((r = sshbuf_get_string(b, sigp, lenp)) != 0) {
- error("%s: buffer error: %s", __func__, ssh_err(r));
+ error_fr(r, "buffer error");
fail:
ssh_signal(SIGCHLD, osigchld);
sshbuf_free(b);
@@ -2030,12 +2109,12 @@ userauth_hostbased(struct ssh *ssh)
int i, r, success = 0;
if (authctxt->ktypes == NULL) {
- authctxt->oktypes = xstrdup(options.hostbased_key_types);
+ authctxt->oktypes = xstrdup(options.hostbased_accepted_algos);
authctxt->ktypes = authctxt->oktypes;
}
/*
- * Work through each listed type pattern in HostbasedKeyTypes,
+ * Work through each listed type pattern in HostbasedAcceptedAlgorithms,
* trying each hostkey that matches the type in turn.
*/
for (;;) {
@@ -2044,8 +2123,7 @@ userauth_hostbased(struct ssh *ssh)
if (authctxt->active_ktype == NULL ||
*authctxt->active_ktype == '\0')
break;
- debug3("%s: trying key type %s", __func__,
- authctxt->active_ktype);
+ debug3_f("trying key type %s", authctxt->active_ktype);
/* check for a useful key */
private = NULL;
@@ -2078,42 +2156,41 @@ userauth_hostbased(struct ssh *ssh)
if ((fp = sshkey_fingerprint(private, options.fingerprint_hash,
SSH_FP_DEFAULT)) == NULL) {
- error("%s: sshkey_fingerprint failed", __func__);
+ error_f("sshkey_fingerprint failed");
goto out;
}
- debug("%s: trying hostkey %s %s",
- __func__, sshkey_ssh_name(private), fp);
+ debug_f("trying hostkey %s %s", sshkey_ssh_name(private), fp);
/* figure out a name for the client host */
lname = get_local_name(ssh_packet_get_connection_in(ssh));
if (lname == NULL) {
- error("%s: cannot get local ipaddr/name", __func__);
+ error_f("cannot get local ipaddr/name");
goto out;
}
/* XXX sshbuf_put_stringf? */
xasprintf(&chost, "%s.", lname);
- debug2("%s: chost %s", __func__, chost);
+ debug2_f("chost %s", chost);
/* construct data */
if ((b = sshbuf_new()) == NULL) {
- error("%s: sshbuf_new failed", __func__);
+ error_f("sshbuf_new failed");
goto out;
}
if ((r = sshkey_to_blob(private, &keyblob, &keylen)) != 0) {
- error("%s: sshkey_to_blob: %s", __func__, ssh_err(r));
+ error_fr(r, "sshkey_to_blob");
goto out;
}
- if ((r = sshbuf_put_string(b, session_id2, session_id2_len)) != 0 ||
+ if ((r = sshbuf_put_stringb(b, ssh->kex->session_id)) != 0 ||
(r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->service)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->method->name)) != 0 ||
- (r = sshbuf_put_cstring(b, sshkey_ssh_name(private))) != 0 ||
+ (r = sshbuf_put_cstring(b, authctxt->active_ktype)) != 0 ||
(r = sshbuf_put_string(b, keyblob, keylen)) != 0 ||
(r = sshbuf_put_cstring(b, chost)) != 0 ||
(r = sshbuf_put_cstring(b, authctxt->local_user)) != 0) {
- error("%s: buffer error: %s", __func__, ssh_err(r));
+ error_fr(r, "buffer error");
goto out;
}
@@ -2130,13 +2207,13 @@ userauth_hostbased(struct ssh *ssh)
(r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
- (r = sshpkt_put_cstring(ssh, sshkey_ssh_name(private))) != 0 ||
+ (r = sshpkt_put_cstring(ssh, authctxt->active_ktype)) != 0 ||
(r = sshpkt_put_string(ssh, keyblob, keylen)) != 0 ||
(r = sshpkt_put_cstring(ssh, chost)) != 0 ||
(r = sshpkt_put_cstring(ssh, authctxt->local_user)) != 0 ||
(r = sshpkt_put_string(ssh, sig, siglen)) != 0 ||
(r = sshpkt_send(ssh)) != 0) {
- error("%s: packet error: %s", __func__, ssh_err(r));
+ error_fr(r, "packet error");
goto out;
}
success = 1;
@@ -2245,17 +2322,16 @@ authmethods_get(void)
int r;
if ((b = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
for (method = authmethods; method->name != NULL; method++) {
if (authmethod_is_enabled(method)) {
if ((r = sshbuf_putf(b, "%s%s",
sshbuf_len(b) ? "," : "", method->name)) != 0)
- fatal("%s: buffer error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "buffer error");
}
}
if ((list = sshbuf_dup_string(b)) == NULL)
- fatal("%s: sshbuf_dup_string failed", __func__);
+ fatal_f("sshbuf_dup_string failed");
sshbuf_free(b);
return list;
}
diff --git a/sshd.8 b/sshd.8
index c5f8987d2..ef38949a2 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.312 2020/01/25 06:03:10 djm Exp $
-.Dd $Mdocdate: January 25 2020 $
+.\" $OpenBSD: sshd.8,v 1.317 2021/09/10 11:38:38 dtucker Exp $
+.Dd $Mdocdate: September 10 2021 $
.Dt SSHD 8
.Os
.Sh NAME
@@ -58,8 +58,7 @@
.Nm
(OpenSSH Daemon) is the daemon program for
.Xr ssh 1 .
-Together these programs replace rlogin and rsh,
-and provide secure encrypted communications between two untrusted hosts
+It provides secure encrypted communications between two untrusted hosts
over an insecure network.
.Pp
.Nm
@@ -107,7 +106,7 @@ supplied in any order, either with multiple
.Fl C
options or as a comma-separated list.
The keywords are
-.Dq addr,
+.Dq addr ,
.Dq user ,
.Dq host ,
.Dq laddr ,
@@ -135,7 +134,9 @@ This allows easy monitoring of
Debug mode.
The server sends verbose debug output to standard error,
and does not put itself in the background.
-The server also will not fork and will only process one connection.
+The server also will not
+.Xr fork 2
+and will only process one connection.
This option is only intended for debugging for the server.
Multiple
.Fl d
@@ -302,7 +303,12 @@ things like allocating a pseudo-tty, forwarding X11 connections,
forwarding TCP connections, or forwarding the authentication agent
connection over the secure channel.
.Pp
-After this, the client either requests a shell or execution of a command.
+After this, the client either requests an interactive shell or execution
+or a non-interactive command, which
+.Nm
+will execute via the user's shell using its
+.Fl c
+option.
The sides then enter session mode.
In this mode, either side may send
data at any time, and such data is forwarded to/from the shell or
@@ -355,7 +361,8 @@ exists and the
option is set, runs it; else if
.Pa /etc/ssh/sshrc
exists, runs
-it; otherwise runs xauth.
+it; otherwise runs
+.Xr xauth 1 .
The
.Dq rc
files are given the X11
@@ -631,6 +638,13 @@ This option only makes sense for the FIDO authenticator algorithms
.Cm ecdsa-sk
and
.Cm ed25519-sk .
+.It Cm verify-required
+Require that signatures made using this key attest that they verified
+the user, e.g. via a PIN.
+This option only makes sense for the FIDO authenticator algorithms
+.Cm ecdsa-sk
+and
+.Cm ed25519-sk .
.It Cm restrict
Enable all restrictions, i.e. disable port, agent and X11 forwarding,
as well as disabling PTY allocation
@@ -658,24 +672,25 @@ option.
.Pp
An example authorized_keys file:
.Bd -literal -offset 3n
-# Comments allowed at start of line
-ssh-rsa AAAAB3Nza...LiPk== user@example.net
-from="*.sales.example.net,!pc.sales.example.net" ssh-rsa
-AAAAB2...19Q== john@example.net
-command="dump /home",no-pty,no-port-forwarding ssh-rsa
-AAAAC3...51R== example.net
-permitopen="192.0.2.1:80",permitopen="192.0.2.2:25" ssh-rsa
-AAAAB5...21S==
-permitlisten="localhost:8080",permitopen="localhost:22000" ssh-rsa
-AAAAB5...21S==
-tunnel="0",command="sh /etc/netstart tun0" ssh-rsa AAAA...==
-jane@example.net
-restrict,command="uptime" ssh-rsa AAAA1C8...32Tv==
-user@example.net
-restrict,pty,command="nethack" ssh-rsa AAAA1f8...IrrC5==
-user@example.net
-no-touch-required sk-ecdsa-sha2-nistp256@openssh.com AAAAInN...Ko==
-user@example.net
+# Comments are allowed at start of line. Blank lines are allowed.
+# Plain key, no restrictions
+ssh-rsa ...
+# Forced command, disable PTY and all forwarding
+restrict,command="dump /home" ssh-rsa ...
+# Restriction of ssh -L forwarding destinations
+permitopen="192.0.2.1:80",permitopen="192.0.2.2:25" ssh-rsa ...
+# Restriction of ssh -R forwarding listeners
+permitlisten="localhost:8080",permitlisten="[::1]:22000" ssh-rsa ...
+# Configuration for tunnel forwarding
+tunnel="0",command="sh /etc/netstart tun0" ssh-rsa ...
+# Override of restriction to allow PTY allocation
+restrict,pty,command="nethack" ssh-rsa ...
+# Allow FIDO key without requiring touch
+no-touch-required sk-ecdsa-sha2-nistp256@openssh.com ...
+# Require user-verification (e.g. PIN or biometric) for FIDO key
+verify-required sk-ecdsa-sha2-nistp256@openssh.com ...
+# Trust CA key, allow touch-less FIDO if requested in certificate
+cert-authority,no-touch-required,principals="user_a" ssh-rsa ...
.Ed
.Sh SSH_KNOWN_HOSTS FILE FORMAT
The
@@ -688,7 +703,7 @@ be prepared by the administrator (optional), and the per-user file is
maintained automatically: whenever the user connects to an unknown host,
its key is added to the per-user file.
.Pp
-Each line in these files contains the following fields: markers (optional),
+Each line in these files contains the following fields: marker (optional),
hostnames, keytype, base64-encoded key, comment.
The fields are separated by spaces.
.Pp
diff --git a/sshd.c b/sshd.c
index fba25e6b8..c738061fc 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshd.c,v 1.552 2020/03/13 04:01:57 djm Exp $ */
+/* $OpenBSD: sshd.c,v 1.578 2021/07/19 02:21:50 dtucker Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -123,6 +123,8 @@
#include "version.h"
#include "ssherr.h"
#include "sk-api.h"
+#include "srclimit.h"
+#include "dh.h"
/* Re-exec fds */
#define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1)
@@ -204,13 +206,6 @@ struct {
static volatile sig_atomic_t received_sighup = 0;
static volatile sig_atomic_t received_sigterm = 0;
-/* session identifier, used by RSA-auth */
-u_char session_id[16];
-
-/* same for ssh2 */
-u_char *session_id2 = NULL;
-u_int session_id2_len = 0;
-
/* record remote hostname or ip */
u_int utmp_len = HOST_NAME_MAX+1;
@@ -346,8 +341,6 @@ main_sigchld_handler(int sig)
pid_t pid;
int status;
- debug("main_sigchld_handler: %s", strsignal(sig));
-
while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
(pid == -1 && errno == EINTR))
;
@@ -373,11 +366,14 @@ grace_alarm_handler(int sig)
kill(0, SIGTERM);
}
- /* XXX pre-format ipaddr/port so we don't need to access active_state */
/* Log error and exit. */
- sigdie("Timeout before authentication for %s port %d",
- ssh_remote_ipaddr(the_active_state),
- ssh_remote_port(the_active_state));
+ if (use_privsep && pmonitor != NULL && pmonitor->m_pid <= 0)
+ cleanup_exit(255); /* don't log in privsep child */
+ else {
+ sigdie("Timeout before authentication for %s port %d",
+ ssh_remote_ipaddr(the_active_state),
+ ssh_remote_port(the_active_state));
+ }
}
/* Destroy the host and server keys. They will no longer be needed. */
@@ -410,9 +406,8 @@ demote_sensitive_data(void)
if (sensitive_data.host_keys[i]) {
if ((r = sshkey_from_private(
sensitive_data.host_keys[i], &tmp)) != 0)
- fatal("could not demote host %s key: %s",
- sshkey_type(sensitive_data.host_keys[i]),
- ssh_err(r));
+ fatal_r(r, "could not demote host %s key",
+ sshkey_type(sensitive_data.host_keys[i]));
sshkey_free(sensitive_data.host_keys[i]);
sensitive_data.host_keys[i] = tmp;
}
@@ -502,8 +497,7 @@ privsep_preauth(struct ssh *ssh)
if (have_agent) {
r = ssh_get_authentication_socket(&auth_sock);
if (r != 0) {
- error("Could not get agent socket: %s",
- ssh_err(r));
+ error_r(r, "Could not get agent socket");
have_agent = 0;
}
}
@@ -516,17 +510,17 @@ privsep_preauth(struct ssh *ssh)
if (errno == EINTR)
continue;
pmonitor->m_pid = -1;
- fatal("%s: waitpid: %s", __func__, strerror(errno));
+ fatal_f("waitpid: %s", strerror(errno));
}
privsep_is_preauth = 0;
pmonitor->m_pid = -1;
if (WIFEXITED(status)) {
if (WEXITSTATUS(status) != 0)
- fatal("%s: preauth child exited with status %d",
- __func__, WEXITSTATUS(status));
+ fatal_f("preauth child exited with status %d",
+ WEXITSTATUS(status));
} else if (WIFSIGNALED(status))
- fatal("%s: preauth child terminated by signal %d",
- __func__, WTERMSIG(status));
+ fatal_f("preauth child terminated by signal %d",
+ WTERMSIG(status));
if (box != NULL)
ssh_sandbox_parent_finish(box);
return 1;
@@ -606,12 +600,11 @@ append_hostkey_type(struct sshbuf *b, const char *s)
int r;
if (match_pattern_list(s, options.hostkeyalgorithms, 0) != 1) {
- debug3("%s: %s key not permitted by HostkeyAlgorithms",
- __func__, s);
+ debug3_f("%s key not permitted by HostkeyAlgorithms", s);
return;
}
if ((r = sshbuf_putf(b, "%s%s", sshbuf_len(b) > 0 ? "," : "", s)) != 0)
- fatal("%s: sshbuf_putf: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_putf");
}
static char *
@@ -623,7 +616,7 @@ list_hostkey_types(void)
u_int i;
if ((b = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
for (i = 0; i < options.num_host_key_files; i++) {
key = sensitive_data.host_keys[i];
if (key == NULL)
@@ -668,9 +661,9 @@ list_hostkey_types(void)
}
}
if ((ret = sshbuf_dup_string(b)) == NULL)
- fatal("%s: sshbuf_dup_string failed", __func__);
+ fatal_f("sshbuf_dup_string failed");
sshbuf_free(b);
- debug("%s: %s", __func__, ret);
+ debug_f("%s", ret);
return ret;
}
@@ -784,7 +777,7 @@ notify_hostkeys(struct ssh *ssh)
return;
if ((buf = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new", __func__);
+ fatal_f("sshbuf_new");
for (i = nkeys = 0; i < options.num_host_key_files; i++) {
key = get_hostkey_public_by_index(i, ssh);
if (key == NULL || key->type == KEY_UNSPEC ||
@@ -792,8 +785,7 @@ notify_hostkeys(struct ssh *ssh)
continue;
fp = sshkey_fingerprint(key, options.fingerprint_hash,
SSH_FP_DEFAULT);
- debug3("%s: key %d: %s %s", __func__, i,
- sshkey_ssh_name(key), fp);
+ debug3_f("key %d: %s %s", i, sshkey_ssh_name(key), fp);
free(fp);
if (nkeys == 0) {
/*
@@ -808,15 +800,14 @@ notify_hostkeys(struct ssh *ssh)
/* Append the key to the request */
sshbuf_reset(buf);
if ((r = sshkey_putb(key, buf)) != 0)
- fatal("%s: couldn't put hostkey %d: %s",
- __func__, i, ssh_err(r));
+ fatal_fr(r, "couldn't put hostkey %d", i);
if ((r = sshpkt_put_stringb(ssh, buf)) != 0)
sshpkt_fatal(ssh, r, "%s: append key", __func__);
nkeys++;
}
- debug3("%s: sent %u hostkeys", __func__, nkeys);
+ debug3_f("sent %u hostkeys", nkeys);
if (nkeys == 0)
- fatal("%s: no hostkeys", __func__);
+ fatal_f("no hostkeys");
if ((r = sshpkt_send(ssh)) != 0)
sshpkt_fatal(ssh, r, "%s: send", __func__);
sshbuf_free(buf);
@@ -829,7 +820,7 @@ notify_hostkeys(struct ssh *ssh)
* all connections are dropped for startups > max_startups
*/
static int
-drop_connection(int startups)
+should_drop_connection(int startups)
{
int p, r;
@@ -846,21 +837,73 @@ drop_connection(int startups)
p += options.max_startups_rate;
r = arc4random_uniform(100);
- debug("drop_connection: p %d, r %d", p, r);
+ debug_f("p %d, r %d", p, r);
return (r < p) ? 1 : 0;
}
+/*
+ * Check whether connection should be accepted by MaxStartups.
+ * Returns 0 if the connection is accepted. If the connection is refused,
+ * returns 1 and attempts to send notification to client.
+ * Logs when the MaxStartups condition is entered or exited, and periodically
+ * while in that state.
+ */
+static int
+drop_connection(int sock, int startups, int notify_pipe)
+{
+ char *laddr, *raddr;
+ const char msg[] = "Exceeded MaxStartups\r\n";
+ static time_t last_drop, first_drop;
+ static u_int ndropped;
+ LogLevel drop_level = SYSLOG_LEVEL_VERBOSE;
+ time_t now;
+
+ now = monotime();
+ if (!should_drop_connection(startups) &&
+ srclimit_check_allow(sock, notify_pipe) == 1) {
+ if (last_drop != 0 &&
+ startups < options.max_startups_begin - 1) {
+ /* XXX maybe need better hysteresis here */
+ logit("exited MaxStartups throttling after %s, "
+ "%u connections dropped",
+ fmt_timeframe(now - first_drop), ndropped);
+ last_drop = 0;
+ }
+ return 0;
+ }
+
+#define SSHD_MAXSTARTUPS_LOG_INTERVAL (5 * 60)
+ if (last_drop == 0) {
+ error("beginning MaxStartups throttling");
+ drop_level = SYSLOG_LEVEL_INFO;
+ first_drop = now;
+ ndropped = 0;
+ } else if (last_drop + SSHD_MAXSTARTUPS_LOG_INTERVAL < now) {
+ /* Periodic logs */
+ error("in MaxStartups throttling for %s, "
+ "%u connections dropped",
+ fmt_timeframe(now - first_drop), ndropped + 1);
+ drop_level = SYSLOG_LEVEL_INFO;
+ }
+ last_drop = now;
+ ndropped++;
+
+ laddr = get_local_ipaddr(sock);
+ raddr = get_peer_ipaddr(sock);
+ do_log2(drop_level, "drop connection #%d from [%s]:%d on [%s]:%d "
+ "past MaxStartups", startups, raddr, get_peer_port(sock),
+ laddr, get_local_port(sock));
+ free(laddr);
+ free(raddr);
+ /* best-effort notification to client */
+ (void)write(sock, msg, sizeof(msg) - 1);
+ return 1;
+}
+
static void
usage(void)
{
- fprintf(stderr, "%s, %s\n",
- SSH_RELEASE,
-#ifdef WITH_OPENSSL
- OpenSSL_version(OPENSSL_VERSION)
-#else
- "without OpenSSL"
-#endif
- );
+ fprintf(stderr, "%s, %s\n", SSH_RELEASE, SSH_OPENSSL_VERSION);
fprintf(stderr,
"usage: sshd [-46DdeiqTt] [-C connection_spec] [-c host_cert_file]\n"
" [-E log_file] [-f config_file] [-g login_grace_time]\n"
@@ -876,18 +919,18 @@ send_rexec_state(int fd, struct sshbuf *conf)
struct include_item *item = NULL;
int r;
- debug3("%s: entering fd = %d config len %zu", __func__, fd,
+ debug3_f("entering fd = %d config len %zu", fd,
sshbuf_len(conf));
if ((m = sshbuf_new()) == NULL || (inc = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
/* pack includes into a string */
TAILQ_FOREACH(item, &includes, entry) {
if ((r = sshbuf_put_cstring(inc, item->selector)) != 0 ||
(r = sshbuf_put_cstring(inc, item->filename)) != 0 ||
(r = sshbuf_put_stringb(inc, item->contents)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose includes");
}
/*
@@ -902,17 +945,17 @@ send_rexec_state(int fd, struct sshbuf *conf)
*/
if ((r = sshbuf_put_stringb(m, conf)) != 0 ||
(r = sshbuf_put_stringb(m, inc)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose config");
#if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY)
rexec_send_rng_seed(m);
#endif
if (ssh_msg_send(fd, 0, m) == -1)
- fatal("%s: ssh_msg_send failed", __func__);
+ error_f("ssh_msg_send failed");
sshbuf_free(m);
sshbuf_free(inc);
- debug3("%s: done", __func__);
+ debug3_f("done");
}
static void
@@ -924,50 +967,48 @@ recv_rexec_state(int fd, struct sshbuf *conf)
int r;
struct include_item *item;
- debug3("%s: entering fd = %d", __func__, fd);
+ debug3_f("entering fd = %d", fd);
if ((m = sshbuf_new()) == NULL || (inc = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if (ssh_msg_recv(fd, m) == -1)
- fatal("%s: ssh_msg_recv failed", __func__);
+ fatal_f("ssh_msg_recv failed");
if ((r = sshbuf_get_u8(m, &ver)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse version");
if (ver != 0)
- fatal("%s: rexec version mismatch", __func__);
+ fatal_f("rexec version mismatch");
if ((r = sshbuf_get_string(m, &cp, &len)) != 0 ||
(r = sshbuf_get_stringb(m, inc)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse config");
#if defined(WITH_OPENSSL) && !defined(OPENSSL_PRNG_ONLY)
rexec_recv_rng_seed(m);
#endif
if (conf != NULL && (r = sshbuf_put(conf, cp, len)))
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_put");
while (sshbuf_len(inc) != 0) {
item = xcalloc(1, sizeof(*item));
if ((item->contents = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if ((r = sshbuf_get_cstring(inc, &item->selector, NULL)) != 0 ||
(r = sshbuf_get_cstring(inc, &item->filename, NULL)) != 0 ||
(r = sshbuf_get_stringb(inc, item->contents)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse includes");
TAILQ_INSERT_TAIL(&includes, item, entry);
}
free(cp);
sshbuf_free(m);
- debug3("%s: done", __func__);
+ debug3_f("done");
}
/* Accept a connection from inetd */
static void
server_accept_inetd(int *sock_in, int *sock_out)
{
- int fd;
-
if (rexeced_flag) {
close(REEXEC_CONFIG_PASS_FD);
*sock_in = *sock_out = dup(STDIN_FILENO);
@@ -980,14 +1021,8 @@ server_accept_inetd(int *sock_in, int *sock_out)
* as our code for setting the descriptors won't work if
* ttyfd happens to be one of those.
*/
- if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
- dup2(fd, STDIN_FILENO);
- dup2(fd, STDOUT_FILENO);
- if (!log_stderr)
- dup2(fd, STDERR_FILENO);
- if (fd > (log_stderr ? STDERR_FILENO : STDOUT_FILENO))
- close(fd);
- }
+ if (stdfd_devnull(1, 1, !log_stderr) == -1)
+ error_f("stdfd_devnull failed");
debug("inetd sockets after dupping: %d, %d", *sock_in, *sock_out);
}
@@ -1071,6 +1106,10 @@ server_listen(void)
{
u_int i;
+ /* Initialise per-source limit tracking. */
+ srclimit_init(options.max_startups, options.per_source_max_startups,
+ options.per_source_masklen_ipv4, options.per_source_masklen_ipv6);
+
for (i = 0; i < options.num_listen_addrs; i++) {
listen_on_addrs(&options.listen_addrs[i]);
freeaddrinfo(options.listen_addrs[i].addrs);
@@ -1102,6 +1141,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
socklen_t fromlen;
pid_t pid;
u_char rnd[256];
+ sigset_t nsigset, osigset;
/* setup fd set for accept */
fdset = NULL;
@@ -1116,10 +1156,31 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
startup_pipes[i] = -1;
/*
+ * Prepare signal mask that we use to block signals that might set
+ * received_sigterm or received_sighup, so that we are guaranteed
+ * to immediately wake up the pselect if a signal is received after
+ * the flag is checked.
+ */
+ sigemptyset(&nsigset);
+ sigaddset(&nsigset, SIGHUP);
+ sigaddset(&nsigset, SIGCHLD);
+ sigaddset(&nsigset, SIGTERM);
+ sigaddset(&nsigset, SIGQUIT);
+
+ /*
* Stay listening for connections until the system crashes or
* the daemon is killed with a signal.
*/
for (;;) {
+ sigprocmask(SIG_BLOCK, &nsigset, &osigset);
+ if (received_sigterm) {
+ logit("Received signal %d; terminating.",
+ (int) received_sigterm);
+ close_listen_socks();
+ if (options.pid_file != NULL)
+ unlink(options.pid_file);
+ exit(received_sigterm == SIGTERM ? 0 : 255);
+ }
if (ostartups != startups) {
setproctitle("%s [listener] %d of %d-%d startups",
listener_proctitle, startups,
@@ -1132,8 +1193,10 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
close_listen_socks();
lameduck = 1;
}
- if (listening <= 0)
+ if (listening <= 0) {
+ sigprocmask(SIG_SETMASK, &osigset, NULL);
sighup_restart();
+ }
}
free(fdset);
fdset = xcalloc(howmany(maxfd + 1, NFDBITS),
@@ -1145,18 +1208,11 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
if (startup_pipes[i] != -1)
FD_SET(startup_pipes[i], fdset);
- /* Wait in select until there is a connection. */
- ret = select(maxfd+1, fdset, NULL, NULL, NULL);
+ /* Wait until a connection arrives or a child exits. */
+ ret = pselect(maxfd+1, fdset, NULL, NULL, NULL, &osigset);
if (ret == -1 && errno != EINTR)
- error("select: %.100s", strerror(errno));
- if (received_sigterm) {
- logit("Received signal %d; terminating.",
- (int) received_sigterm);
- close_listen_socks();
- if (options.pid_file != NULL)
- unlink(options.pid_file);
- exit(received_sigterm == SIGTERM ? 0 : 255);
- }
+ error("pselect: %.100s", strerror(errno));
+ sigprocmask(SIG_SETMASK, &osigset, NULL);
if (ret == -1)
continue;
@@ -1169,14 +1225,15 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
if (errno == EINTR || errno == EAGAIN)
continue;
if (errno != EPIPE) {
- error("%s: startup pipe %d (fd=%d): "
- "read %s", __func__, i,
- startup_pipes[i], strerror(errno));
+ error_f("startup pipe %d (fd=%d): "
+ "read %s", i, startup_pipes[i],
+ strerror(errno));
}
/* FALLTHROUGH */
case 0:
/* child exited or completed auth */
close(startup_pipes[i]);
+ srclimit_done(startup_pipes[i]);
startup_pipes[i] = -1;
startups--;
if (startup_flags[i])
@@ -1206,28 +1263,13 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
usleep(100 * 1000);
continue;
}
- if (unset_nonblock(*newsock) == -1) {
- close(*newsock);
+ if (unset_nonblock(*newsock) == -1 ||
+ pipe(startup_p) == -1)
continue;
- }
- if (drop_connection(startups) == 1) {
- char *laddr = get_local_ipaddr(*newsock);
- char *raddr = get_peer_ipaddr(*newsock);
- char msg[] = "Exceeded MaxStartups\r\n";
-
- verbose("drop connection #%d from [%s]:%d "
- "on [%s]:%d past MaxStartups", startups,
- raddr, get_peer_port(*newsock),
- laddr, get_local_port(*newsock));
- free(laddr);
- free(raddr);
- /* best-effort notification to client */
- (void)write(*newsock, msg, strlen(msg));
- close(*newsock);
- continue;
- }
- if (pipe(startup_p) == -1) {
+ if (drop_connection(*newsock, startups, startup_p[0])) {
close(*newsock);
+ close(startup_p[0]);
+ close(startup_p[1]);
continue;
}
@@ -1328,9 +1370,9 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
close(startup_p[1]);
if (rexec_flag) {
+ close(config_s[1]);
send_rexec_state(config_s[0], cfg);
close(config_s[0]);
- close(config_s[1]);
}
close(*newsock);
@@ -1426,7 +1468,7 @@ set_process_rdomain(struct ssh *ssh, const char *name)
if (rtable != ortable && setrtable(rtable) != 0)
fatal("Unable to set routing domain %d: %s",
rtable, strerror(errno));
- debug("%s: set routing domain %d (was %d)", __func__, rtable, ortable);
+ debug_f("set routing domain %d (was %d)", rtable, ortable);
#else /* defined(__OpenBSD__) */
fatal("Unable to set routing domain: not supported in this platform");
#endif
@@ -1443,16 +1485,16 @@ accumulate_host_timing_secret(struct sshbuf *server_cfg,
int r;
if (ctx == NULL && (ctx = ssh_digest_start(SSH_DIGEST_SHA512)) == NULL)
- fatal("%s: ssh_digest_start", __func__);
+ fatal_f("ssh_digest_start");
if (key == NULL) { /* finalize */
/* add server config in case we are using agent for host keys */
if (ssh_digest_update(ctx, sshbuf_ptr(server_cfg),
sshbuf_len(server_cfg)) != 0)
- fatal("%s: ssh_digest_update", __func__);
+ fatal_f("ssh_digest_update");
len = ssh_digest_bytes(SSH_DIGEST_SHA512);
hash = xmalloc(len);
if (ssh_digest_final(ctx, hash, len) != 0)
- fatal("%s: ssh_digest_final", __func__);
+ fatal_f("ssh_digest_final");
options.timing_secret = PEEK_U64(hash);
freezero(hash, len);
ssh_digest_free(ctx);
@@ -1460,11 +1502,11 @@ accumulate_host_timing_secret(struct sshbuf *server_cfg,
return;
}
if ((buf = sshbuf_new()) == NULL)
- fatal("%s could not allocate buffer", __func__);
+ fatal_f("could not allocate buffer");
if ((r = sshkey_private_serialize(key, buf)) != 0)
- fatal("sshkey_private_serialize: %s", ssh_err(r));
+ fatal_fr(r, "decode key");
if (ssh_digest_update(ctx, sshbuf_ptr(buf), sshbuf_len(buf)) != 0)
- fatal("%s: ssh_digest_update", __func__);
+ fatal_f("ssh_digest_update");
sshbuf_reset(buf);
sshbuf_free(buf);
}
@@ -1680,12 +1722,13 @@ main(int ac, char **av)
*/
if (test_flag < 2 && connection_info != NULL)
fatal("Config test connection parameter (-C) provided without "
- "test mode (-T)");
+ "test mode (-T)");
/* Fetch our configuration */
if ((cfg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if (rexeced_flag) {
+ setproctitle("%s", "[rexeced]");
recv_rexec_state(REEXEC_CONFIG_PASS_FD, cfg);
if (!debug_flag) {
startup_pipe = dup(REEXEC_STARTUP_PIPE_FD);
@@ -1702,13 +1745,14 @@ main(int ac, char **av)
parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
cfg, &includes, NULL);
+#ifdef WITH_OPENSSL
+ if (options.moduli_file != NULL)
+ dh_set_moduli_file(options.moduli_file);
+#endif
+
/* Fill in default values for those options not explicitly set. */
fill_default_server_options(&options);
- /* challenge-response is implemented via keyboard interactive */
- if (options.challenge_response_authentication)
- options.kbd_interactive_authentication = 1;
-
/* Check that options are sensible */
if (options.authorized_keys_command_user == NULL &&
(options.authorized_keys_command != NULL &&
@@ -1744,13 +1788,7 @@ main(int ac, char **av)
exit(1);
}
- debug("sshd version %s, %s", SSH_VERSION,
-#ifdef WITH_OPENSSL
- OpenSSL_version(OPENSSL_VERSION)
-#else
- "without OpenSSL"
-#endif
- );
+ debug("sshd version %s, %s", SSH_VERSION, SSH_OPENSSL_VERSION);
/* Store privilege separation user for later use if required. */
privsep_chroot = use_privsep && (getuid() == 0 || geteuid() == 0);
@@ -1780,8 +1818,8 @@ main(int ac, char **av)
if ((r = ssh_get_authentication_socket(NULL)) == 0)
have_agent = 1;
else
- error("Could not connect to agent \"%s\": %s",
- options.host_key_agent, ssh_err(r));
+ error_r(r, "Could not connect to agent \"%s\"",
+ options.host_key_agent);
}
for (i = 0; i < options.num_host_key_files; i++) {
@@ -1792,8 +1830,8 @@ main(int ac, char **av)
continue;
if ((r = sshkey_load_private(options.host_key_files[i], "",
&key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR)
- do_log2(ll, "Unable to load host key \"%s\": %s",
- options.host_key_files[i], ssh_err(r));
+ do_log2_r(r, ll, "Unable to load host key \"%s\"",
+ options.host_key_files[i]);
if (sshkey_is_sk(key) &&
key->sk_flags & SSH_SK_USER_PRESENCE_REQD) {
debug("host key %s requires user presence, ignoring",
@@ -1802,19 +1840,28 @@ main(int ac, char **av)
}
if (r == 0 && key != NULL &&
(r = sshkey_shield_private(key)) != 0) {
- do_log2(ll, "Unable to shield host key \"%s\": %s",
- options.host_key_files[i], ssh_err(r));
+ do_log2_r(r, ll, "Unable to shield host key \"%s\"",
+ options.host_key_files[i]);
sshkey_free(key);
key = NULL;
}
if ((r = sshkey_load_public(options.host_key_files[i],
&pubkey, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR)
- do_log2(ll, "Unable to load host key \"%s\": %s",
- options.host_key_files[i], ssh_err(r));
- if (pubkey == NULL && key != NULL)
+ do_log2_r(r, ll, "Unable to load host key \"%s\"",
+ options.host_key_files[i]);
+ if (pubkey != NULL && key != NULL) {
+ if (!sshkey_equal(pubkey, key)) {
+ error("Public key for %s does not match "
+ "private key", options.host_key_files[i]);
+ sshkey_free(pubkey);
+ pubkey = NULL;
+ }
+ }
+ if (pubkey == NULL && key != NULL) {
if ((r = sshkey_from_private(key, &pubkey)) != 0)
- fatal("Could not demote key: \"%s\": %s",
- options.host_key_files[i], ssh_err(r));
+ fatal_r(r, "Could not demote key: \"%s\"",
+ options.host_key_files[i]);
+ }
sensitive_data.host_keys[i] = key;
sensitive_data.host_pubkeys[i] = pubkey;
@@ -1872,8 +1919,8 @@ main(int ac, char **av)
continue;
if ((r = sshkey_load_public(options.host_cert_files[i],
&key, NULL)) != 0) {
- error("Could not load host certificate \"%s\": %s",
- options.host_cert_files[i], ssh_err(r));
+ error_r(r, "Could not load host certificate \"%s\"",
+ options.host_cert_files[i]);
continue;
}
if (!sshkey_is_cert(key)) {
@@ -1885,7 +1932,7 @@ main(int ac, char **av)
/* Find matching private key */
for (j = 0; j < options.num_host_key_files; j++) {
if (sshkey_equal_public(key,
- sensitive_data.host_keys[j])) {
+ sensitive_data.host_pubkeys[j])) {
sensitive_data.host_certificates[j] = key;
break;
}
@@ -1966,7 +2013,10 @@ main(int ac, char **av)
/* Initialize the log (it is reinitialized below in case we forked). */
if (debug_flag && (!inetd_flag || rexeced_flag))
log_stderr = 1;
- log_init(__progname, options.log_level, options.log_facility, log_stderr);
+ log_init(__progname, options.log_level,
+ options.log_facility, log_stderr);
+ for (i = 0; i < options.num_log_verbose; i++)
+ log_verbose_add(options.log_verbose[i]);
/*
* If not in debugging mode, not started from inetd and not already
@@ -1984,8 +2034,10 @@ main(int ac, char **av)
/* Reinitialize the log (because of the fork above). */
log_init(__progname, options.log_level, options.log_facility, log_stderr);
- /* Chdir to the root directory so that the current disk can be
- unmounted if desired. */
+ /*
+ * Chdir to the root directory so that the current disk can be
+ * unmounted if desired.
+ */
if (chdir("/") == -1)
error("chdir(\"/\"): %s", strerror(errno));
@@ -2044,8 +2096,6 @@ main(int ac, char **av)
#endif
if (rexec_flag) {
- int fd;
-
debug("rexec start in %d out %d newsock %d pipe %d sock %d",
sock_in, sock_out, newsock, startup_pipe, config_s[0]);
dup2(newsock, STDIN_FILENO);
@@ -2061,6 +2111,7 @@ main(int ac, char **av)
dup2(config_s[1], REEXEC_CONFIG_PASS_FD);
close(config_s[1]);
+ ssh_signal(SIGHUP, SIG_IGN); /* avoid reset to SIG_DFL */
execv(rexec_argv[0], rexec_argv);
/* Reexec has failed, fall back and continue */
@@ -2072,12 +2123,8 @@ main(int ac, char **av)
/* Clean up fds */
close(REEXEC_CONFIG_PASS_FD);
newsock = sock_out = sock_in = dup(STDIN_FILENO);
- if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
- dup2(fd, STDIN_FILENO);
- dup2(fd, STDOUT_FILENO);
- if (fd > STDERR_FILENO)
- close(fd);
- }
+ if (stdfd_devnull(1, 1, 0) == -1)
+ error_f("stdfd_devnull failed");
debug("rexec cleanup in %d out %d newsock %d pipe %d sock %d",
sock_in, sock_out, newsock, startup_pipe, config_s[0]);
}
@@ -2178,7 +2225,7 @@ main(int ac, char **av)
/* prepare buffer to collect messages to display to user after login */
if ((loginmsg = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
auth_debug_reset();
if (use_privsep) {
@@ -2186,7 +2233,7 @@ main(int ac, char **av)
goto authenticated;
} else if (have_agent) {
if ((r = ssh_get_authentication_socket(&auth_sock)) != 0) {
- error("Unable to get agent socket: %s", ssh_err(r));
+ error_r(r, "Unable to get agent socket");
have_agent = 0;
}
}
@@ -2289,26 +2336,25 @@ sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey,
if (use_privsep) {
if (privkey) {
if (mm_sshkey_sign(ssh, privkey, signature, slenp,
- data, dlen, alg, options.sk_provider,
+ data, dlen, alg, options.sk_provider, NULL,
ssh->compat) < 0)
- fatal("%s: privkey sign failed", __func__);
+ fatal_f("privkey sign failed");
} else {
if (mm_sshkey_sign(ssh, pubkey, signature, slenp,
- data, dlen, alg, options.sk_provider,
+ data, dlen, alg, options.sk_provider, NULL,
ssh->compat) < 0)
- fatal("%s: pubkey sign failed", __func__);
+ fatal_f("pubkey sign failed");
}
} else {
if (privkey) {
if (sshkey_sign(privkey, signature, slenp, data, dlen,
- alg, options.sk_provider, ssh->compat) < 0)
- fatal("%s: privkey sign failed", __func__);
+ alg, options.sk_provider, NULL, ssh->compat) < 0)
+ fatal_f("privkey sign failed");
} else {
if ((r = ssh_agent_sign(auth_sock, pubkey,
signature, slenp, data, dlen, alg,
ssh->compat)) != 0) {
- fatal("%s: agent sign failed: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "agent sign failed");
}
}
}
@@ -2323,11 +2369,11 @@ do_ssh2_kex(struct ssh *ssh)
struct kex *kex;
int r;
- myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
+ myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(ssh,
options.kex_algorithms);
- myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal(
+ myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal(ssh,
options.ciphers);
- myproposal[PROPOSAL_ENC_ALGS_STOC] = compat_cipher_proposal(
+ myproposal[PROPOSAL_ENC_ALGS_STOC] = compat_cipher_proposal(ssh,
options.ciphers);
myproposal[PROPOSAL_MAC_ALGS_CTOS] =
myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
@@ -2342,11 +2388,11 @@ do_ssh2_kex(struct ssh *ssh)
options.rekey_interval);
myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal(
- list_hostkey_types());
+ ssh, list_hostkey_types());
/* start key exchange */
if ((r = kex_setup(ssh, myproposal)) != 0)
- fatal("kex_setup: %s", ssh_err(r));
+ fatal_r(r, "kex_setup");
kex = ssh->kex;
#ifdef WITH_OPENSSL
kex->kex[KEX_DH_GRP1_SHA1] = kex_gen_server;
@@ -2361,7 +2407,7 @@ do_ssh2_kex(struct ssh *ssh)
# endif
#endif
kex->kex[KEX_C25519_SHA256] = kex_gen_server;
- kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server;
+ kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server;
kex->load_host_public_key=&get_hostkey_public_by_type;
kex->load_host_private_key=&get_hostkey_private_by_type;
kex->host_key_index=&get_hostkey_index;
@@ -2369,15 +2415,13 @@ do_ssh2_kex(struct ssh *ssh)
ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &kex->done);
- session_id2 = kex->session_id;
- session_id2_len = kex->session_id_len;
-
#ifdef DEBUG_KEXDH
/* send 1st encrypted/maced/compressed message */
- packet_start(SSH2_MSG_IGNORE);
- packet_put_cstring("markus");
- packet_send();
- packet_write_wait();
+ if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 ||
+ (r = sshpkt_put_cstring(ssh, "markus")) != 0 ||
+ (r = sshpkt_send(ssh)) != 0 ||
+ (r = ssh_packet_write_wait(ssh)) != 0)
+ fatal_fr(r, "send test");
#endif
debug("KEX done");
}
@@ -2392,9 +2436,10 @@ cleanup_exit(int i)
pmonitor != NULL && pmonitor->m_pid > 1) {
debug("Killing privsep child %d", pmonitor->m_pid);
if (kill(pmonitor->m_pid, SIGKILL) != 0 &&
- errno != ESRCH)
- error("%s: kill(%d): %s", __func__,
- pmonitor->m_pid, strerror(errno));
+ errno != ESRCH) {
+ error_f("kill(%d): %s", pmonitor->m_pid,
+ strerror(errno));
+ }
}
}
#ifdef SSH_AUDIT_EVENTS
diff --git a/sshd_config b/sshd_config
index 19b7c91a1..c423eba1b 100644
--- a/sshd_config
+++ b/sshd_config
@@ -1,4 +1,4 @@
-# $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $
+# $OpenBSD: sshd_config,v 1.104 2021/07/02 05:11:21 dtucker Exp $
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
@@ -58,7 +58,7 @@ AuthorizedKeysFile .ssh/authorized_keys
#PermitEmptyPasswords no
# Change to no to disable s/key passwords
-#ChallengeResponseAuthentication yes
+#KbdInteractiveAuthentication yes
# Kerberos options
#KerberosAuthentication no
@@ -72,13 +72,13 @@ AuthorizedKeysFile .ssh/authorized_keys
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
-# be allowed through the ChallengeResponseAuthentication and
+# be allowed through the KbdInteractiveAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
-# PAM authentication via ChallengeResponseAuthentication may bypass
+# PAM authentication via KbdInteractiveAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
-# and ChallengeResponseAuthentication to 'no'.
+# and KbdInteractiveAuthentication to 'no'.
#UsePAM no
#AllowAgentForwarding yes
diff --git a/sshd_config.5 b/sshd_config.5
index b294efc2d..a8d0545c3 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.311 2020/04/17 06:12:41 jmc Exp $
-.Dd $Mdocdate: April 17 2020 $
+.\" $OpenBSD: sshd_config.5,v 1.335 2021/09/03 05:25:50 dtucker Exp $
+.Dd $Mdocdate: September 3 2021 $
.Dt SSHD_CONFIG 5
.Os
.Sh NAME
@@ -377,18 +377,24 @@ Specifies which algorithms are allowed for signing of certificates
by certificate authorities (CAs).
The default is:
.Bd -literal -offset indent
-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
-ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
+ssh-ed25519,ecdsa-sha2-nistp256,
+ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+sk-ssh-ed25519@openssh.com,
+sk-ecdsa-sha2-nistp256@openssh.com,
+rsa-sha2-512,rsa-sha2-256
.Ed
.Pp
+If the specified list begins with a
+.Sq +
+character, then the specified algorithms will be appended to the default set
+instead of replacing them.
+If the specified list begins with a
+.Sq -
+character, then the specified algorithms (including wildcards) will be removed
+from the default set instead of replacing them.
+.Pp
Certificates signed using other algorithms will not be accepted for
public key or host-based authentication.
-.It Cm ChallengeResponseAuthentication
-Specifies whether challenge-response authentication is allowed (e.g. via
-PAM or through authentication styles supported in
-.Xr login.conf 5 )
-The default is
-.Cm yes .
.It Cm ChrootDirectory
Specifies the pathname of a directory to
.Xr chroot 2
@@ -658,40 +664,42 @@ machine's default store.
This facility is provided to assist with operation on multi homed machines.
The default is
.Cm yes .
-.It Cm HostbasedAcceptedKeyTypes
-Specifies the key types that will be accepted for hostbased authentication
-as a list of comma-separated patterns.
+.It Cm HostbasedAcceptedAlgorithms
+Specifies the signature algorithms that will be accepted for hostbased
+authentication as a list of comma-separated patterns.
Alternately if the specified list begins with a
.Sq +
-character, then the specified key types will be appended to the default set
-instead of replacing them.
+character, then the specified signature algorithms will be appended to
+the default set instead of replacing them.
If the specified list begins with a
.Sq -
-character, then the specified key types (including wildcards) will be removed
-from the default set instead of replacing them.
+character, then the specified signature algorithms (including wildcards)
+will be removed from the default set instead of replacing them.
If the specified list begins with a
.Sq ^
-character, then the specified key types will be placed at the head of the
-default set.
+character, then the specified signature algorithms will be placed at
+the head of the default set.
The default for this option is:
.Bd -literal -offset 3n
+ssh-ed25519-cert-v01@openssh.com,
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ssh-ed25519-cert-v01@openssh.com,
sk-ssh-ed25519-cert-v01@openssh.com,
+sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,
rsa-sha2-256-cert-v01@openssh.com,
ssh-rsa-cert-v01@openssh.com,
+ssh-ed25519,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+sk-ssh-ed25519@openssh.com,
sk-ecdsa-sha2-nistp256@openssh.com,
-ssh-ed25519,sk-ssh-ed25519@openssh.com,
rsa-sha2-512,rsa-sha2-256,ssh-rsa
.Ed
.Pp
-The list of available key types may also be obtained using
-.Qq ssh -Q HostbasedAcceptedKeyTypes .
+The list of available signature algorithms may also be obtained using
+.Qq ssh -Q HostbasedAcceptedAlgorithms .
+This was formerly named HostbasedAcceptedKeyTypes.
.It Cm HostbasedAuthentication
Specifies whether rhosts or /etc/hosts.equiv authentication together
with successful public key client host authentication is allowed
@@ -754,26 +762,27 @@ is specified, the location of the socket will be read from the
.Ev SSH_AUTH_SOCK
environment variable.
.It Cm HostKeyAlgorithms
-Specifies the host key algorithms
+Specifies the host key signature algorithms
that the server offers.
The default for this option is:
.Bd -literal -offset 3n
+ssh-ed25519-cert-v01@openssh.com,
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ssh-ed25519-cert-v01@openssh.com,
sk-ssh-ed25519-cert-v01@openssh.com,
+sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,
rsa-sha2-256-cert-v01@openssh.com,
ssh-rsa-cert-v01@openssh.com,
+ssh-ed25519,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+sk-ssh-ed25519@openssh.com,
sk-ecdsa-sha2-nistp256@openssh.com,
-ssh-ed25519,sk-ssh-ed25519@openssh.com,
rsa-sha2-512,rsa-sha2-256,ssh-rsa
.Ed
.Pp
-The list of available key types may also be obtained using
+The list of available signature algorithms may also be obtained using
.Qq ssh -Q HostKeyAlgorithms .
.It Cm IgnoreRhosts
Specifies whether to ignore per-user
@@ -817,7 +826,7 @@ The default is
Include the specified configuration file(s).
Multiple pathnames may be specified and each pathname may contain
.Xr glob 7
-wildcards.
+wildcards that will be expanded and processed in lexical order.
Files without absolute paths are assumed to be in
.Pa /etc/ssh .
An
@@ -870,15 +879,17 @@ for interactive sessions and
for non-interactive sessions.
.It Cm KbdInteractiveAuthentication
Specifies whether to allow keyboard-interactive authentication.
+All authentication styles from
+.Xr login.conf 5
+are supported.
+The default is
+.Cm yes .
The argument to this keyword must be
.Cm yes
or
.Cm no .
-The default is to use whatever value
.Cm ChallengeResponseAuthentication
-is set to
-(by default
-.Cm yes ) .
+is a deprecated alias for this.
.It Cm KerberosAuthentication
Specifies whether the password provided by the user for
.Cm PasswordAuthentication
@@ -909,15 +920,15 @@ Specifies the available KEX (Key Exchange) algorithms.
Multiple algorithms must be comma-separated.
Alternately if the specified list begins with a
.Sq +
-character, then the specified methods will be appended to the default set
+character, then the specified algorithms will be appended to the default set
instead of replacing them.
If the specified list begins with a
.Sq -
-character, then the specified methods (including wildcards) will be removed
+character, then the specified algorithms (including wildcards) will be removed
from the default set instead of replacing them.
If the specified list begins with a
.Sq ^
-character, then the specified methods will be placed at the head of the
+character, then the specified algorithms will be placed at the head of the
default set.
The supported algorithms are:
.Pp
@@ -947,7 +958,7 @@ ecdh-sha2-nistp384
.It
ecdh-sha2-nistp521
.It
-sntrup4591761x25519-sha512@tinyssh.org
+sntrup761x25519-sha512@openssh.com
.El
.Pp
The default is:
@@ -1026,6 +1037,23 @@ The default is INFO.
DEBUG and DEBUG1 are equivalent.
DEBUG2 and DEBUG3 each specify higher levels of debugging output.
Logging with a DEBUG level violates the privacy of users and is not recommended.
+.It Cm LogVerbose
+Specify one or more overrides to LogLevel.
+An override consists of a pattern lists that matches the source file, function
+and line number to force detailed logging for.
+For example, an override pattern of:
+.Bd -literal -offset indent
+kex.c:*:1000,*:kex_exchange_identification():*,packet.c:*
+.Ed
+.Pp
+would enable detailed logging for line 1000 of
+.Pa kex.c ,
+everything in the
+.Fn kex_exchange_identification
+function, and all code in the
+.Pa packet.c
+file.
+This option is intended for debugging and no overrides are enabled by default.
.It Cm MACs
Specifies the available MAC (message authentication code) algorithms.
The MAC algorithm is used for data integrity protection.
@@ -1167,10 +1195,11 @@ Available keywords are
.Cm ClientAliveInterval ,
.Cm DenyGroups ,
.Cm DenyUsers ,
+.Cm DisableForwarding ,
.Cm ForceCommand ,
.Cm GatewayPorts ,
.Cm GSSAPIAuthentication ,
-.Cm HostbasedAcceptedKeyTypes ,
+.Cm HostbasedAcceptedAlgorithms ,
.Cm HostbasedAuthentication ,
.Cm HostbasedUsesNameFromPacketOnly ,
.Cm IgnoreRhosts ,
@@ -1189,7 +1218,7 @@ Available keywords are
.Cm PermitTTY ,
.Cm PermitTunnel ,
.Cm PermitUserRC ,
-.Cm PubkeyAcceptedKeyTypes ,
+.Cm PubkeyAcceptedAlgorithms ,
.Cm PubkeyAuthentication ,
.Cm RekeyLimit ,
.Cm RevokedKeys ,
@@ -1235,6 +1264,16 @@ will refuse connection attempts with a probability of rate/100 (30%)
if there are currently start (10) unauthenticated connections.
The probability increases linearly and all connection attempts
are refused if the number of unauthenticated connections reaches full (60).
+.It Cm ModuliFile
+Specifies the
+.Xr moduli 5
+file that contains the Diffie-Hellman groups used for the
+.Dq diffie-hellman-group-exchange-sha1
+and
+.Dq diffie-hellman-group-exchange-sha256
+key exchange methods.
+The default is
+.Pa /etc/moduli .
.It Cm PasswordAuthentication
Specifies whether password authentication is allowed.
The default is
@@ -1407,6 +1446,23 @@ Specifies whether any
file is executed.
The default is
.Cm yes .
+.It Cm PerSourceMaxStartups
+Specifies the number of unauthenticated connections allowed from a
+given source address, or
+.Dq none
+if there is no limit.
+This limit is applied in addition to
+.Cm MaxStartups ,
+whichever is lower.
+The default is
+.Cm none .
+.It Cm PerSourceNetBlockSize
+Specifies the number of bits of source address that are grouped together
+for the purposes of applying PerSourceMaxStartups limits.
+Values for IPv4 and optionally IPv6 may be specified, separated by a colon.
+The default is
+.Cm 32:128 ,
+which means each address is considered individually.
.It Cm PidFile
Specifies the file that contains the process ID of the
SSH daemon, or
@@ -1440,47 +1496,49 @@ when a user logs in interactively.
or equivalent.)
The default is
.Cm yes .
-.It Cm PubkeyAcceptedKeyTypes
-Specifies the key types that will be accepted for public key authentication
-as a list of comma-separated patterns.
+.It Cm PubkeyAcceptedAlgorithms
+Specifies the signature algorithms that will be accepted for public key
+authentication as a list of comma-separated patterns.
Alternately if the specified list begins with a
.Sq +
-character, then the specified key types will be appended to the default set
+character, then the specified algorithms will be appended to the default set
instead of replacing them.
If the specified list begins with a
.Sq -
-character, then the specified key types (including wildcards) will be removed
+character, then the specified algorithms (including wildcards) will be removed
from the default set instead of replacing them.
If the specified list begins with a
.Sq ^
-character, then the specified key types will be placed at the head of the
+character, then the specified algorithms will be placed at the head of the
default set.
The default for this option is:
.Bd -literal -offset 3n
+ssh-ed25519-cert-v01@openssh.com,
ecdsa-sha2-nistp256-cert-v01@openssh.com,
ecdsa-sha2-nistp384-cert-v01@openssh.com,
ecdsa-sha2-nistp521-cert-v01@openssh.com,
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
-ssh-ed25519-cert-v01@openssh.com,
sk-ssh-ed25519-cert-v01@openssh.com,
+sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
rsa-sha2-512-cert-v01@openssh.com,
rsa-sha2-256-cert-v01@openssh.com,
ssh-rsa-cert-v01@openssh.com,
+ssh-ed25519,
ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
+sk-ssh-ed25519@openssh.com,
sk-ecdsa-sha2-nistp256@openssh.com,
-ssh-ed25519,sk-ssh-ed25519@openssh.com,
rsa-sha2-512,rsa-sha2-256,ssh-rsa
.Ed
.Pp
-The list of available key types may also be obtained using
-.Qq ssh -Q PubkeyAcceptedKeyTypes .
+The list of available signature algorithms may also be obtained using
+.Qq ssh -Q PubkeyAcceptedAlgorithms .
.It Cm PubkeyAuthOptions
Sets one or more public key authentication options.
-Two option keywords are currently supported:
+The supported keywords are:
.Cm none
-(the default; indicating no additional options are enabled)
+(the default; indicating no additional options are enabled),
+.Cm touch-required
and
-.Cm touch-required .
+.Cm verify-required .
.Pp
The
.Cm touch-required
@@ -1497,14 +1555,24 @@ requires user presence unless overridden with an authorized_keys option.
The
.Cm touch-required
flag disables this override.
-This option has no effect for other, non-authenticator public key types.
+.Pp
+The
+.Cm verify-required
+option requires a FIDO key signature attest that the user was verified,
+e.g. via a PIN.
+.Pp
+Neither the
+.Cm touch-required
+or
+.Cm verify-required
+options have any effect for other, non-FIDO, public key types.
.It Cm PubkeyAuthentication
Specifies whether public key authentication is allowed.
The default is
.Cm yes .
.It Cm RekeyLimit
Specifies the maximum amount of data that may be transmitted before the
-session key is renegotiated, optionally followed a maximum amount of
+session key is renegotiated, optionally followed by a maximum amount of
time that may pass before the session key is renegotiated.
The first argument is specified in bytes and may have a suffix of
.Sq K ,
@@ -1542,7 +1610,7 @@ For more information on KRLs, see the KEY REVOCATION LISTS section in
.It Cm RDomain
Specifies an explicit routing domain that is applied after authentication
has completed.
-The user session, as well and any forwarded or listening IP sockets,
+The user session, as well as any forwarded or listening IP sockets,
will be bound to this
.Xr rdomain 4 .
If the routing domain is set to
@@ -1688,17 +1756,17 @@ Enables the Pluggable Authentication Module interface.
If set to
.Cm yes
this will enable PAM authentication using
-.Cm ChallengeResponseAuthentication
+.Cm KbdInteractiveAuthentication
and
.Cm PasswordAuthentication
in addition to PAM account and session module processing for all
authentication types.
.Pp
-Because PAM challenge-response authentication usually serves an equivalent
+Because PAM keyboard-interactive authentication usually serves an equivalent
role to password authentication, you should disable either
.Cm PasswordAuthentication
or
-.Cm ChallengeResponseAuthentication.
+.Cm KbdInteractiveAuthentication .
.Pp
If
.Cm UsePAM
diff --git a/sshkey-xmss.c b/sshkey-xmss.c
index 88e9ddf4d..f5235ef2f 100644
--- a/sshkey-xmss.c
+++ b/sshkey-xmss.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey-xmss.c,v 1.8 2019/11/13 07:53:10 markus Exp $ */
+/* $OpenBSD: sshkey-xmss.c,v 1.11 2021/04/03 06:18:41 djm Exp $ */
/*
* Copyright (c) 2017 Markus Friedl. All rights reserved.
*
@@ -45,6 +45,7 @@
#include "sshkey.h"
#include "sshkey-xmss.h"
#include "atomicio.h"
+#include "log.h"
#include "xmss_fast.h"
@@ -79,7 +80,7 @@ int sshkey_xmss_init_bds_state(struct sshkey *);
int sshkey_xmss_init_enc_key(struct sshkey *, const char *);
void sshkey_xmss_free_bds(struct sshkey *);
int sshkey_xmss_get_state_from_file(struct sshkey *, const char *,
- int *, sshkey_printfn *);
+ int *, int);
int sshkey_xmss_encrypt_state(const struct sshkey *, struct sshbuf *,
struct sshbuf **);
int sshkey_xmss_decrypt_state(const struct sshkey *, struct sshbuf *,
@@ -87,7 +88,8 @@ int sshkey_xmss_decrypt_state(const struct sshkey *, struct sshbuf *,
int sshkey_xmss_serialize_enc_key(const struct sshkey *, struct sshbuf *);
int sshkey_xmss_deserialize_enc_key(struct sshkey *, struct sshbuf *);
-#define PRINT(s...) do { if (pr) pr(s); } while (0)
+#define PRINT(...) do { if (printerror) sshlog(__FILE__, __func__, __LINE__, \
+ 0, SYSLOG_LEVEL_ERROR, NULL, __VA_ARGS__); } while (0)
int
sshkey_xmss_init(struct sshkey *key, const char *name)
@@ -392,7 +394,7 @@ sshkey_xmss_generate_private_key(struct sshkey *k, u_int bits)
int
sshkey_xmss_get_state_from_file(struct sshkey *k, const char *filename,
- int *have_file, sshkey_printfn *pr)
+ int *have_file, int printerror)
{
struct sshbuf *b = NULL, *enc = NULL;
int ret = SSH_ERR_SYSTEM_ERROR, r, fd = -1;
@@ -403,7 +405,7 @@ sshkey_xmss_get_state_from_file(struct sshkey *k, const char *filename,
if ((fd = open(filename, O_RDONLY)) >= 0) {
*have_file = 1;
if (atomicio(read, fd, buf, sizeof(buf)) != sizeof(buf)) {
- PRINT("%s: corrupt state file: %s", __func__, filename);
+ PRINT("corrupt state file: %s", filename);
goto done;
}
len = PEEK_U32(buf);
@@ -412,7 +414,7 @@ sshkey_xmss_get_state_from_file(struct sshkey *k, const char *filename,
goto done;
}
if (atomicio(read, fd, data, len) != len) {
- PRINT("%s: cannot read blob: %s", __func__, filename);
+ PRINT("cannot read blob: %s", filename);
goto done;
}
if ((enc = sshbuf_from(data, len)) == NULL) {
@@ -440,7 +442,7 @@ done:
}
int
-sshkey_xmss_get_state(const struct sshkey *k, sshkey_printfn *pr)
+sshkey_xmss_get_state(const struct sshkey *k, int printerror)
{
struct ssh_xmss_state *state = k->xmss_state;
u_int32_t idx = 0;
@@ -475,27 +477,27 @@ sshkey_xmss_get_state(const struct sshkey *k, sshkey_printfn *pr)
}
if ((lockfd = open(lockfile, O_CREAT|O_RDONLY, 0600)) == -1) {
ret = SSH_ERR_SYSTEM_ERROR;
- PRINT("%s: cannot open/create: %s", __func__, lockfile);
+ 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("%s: cannot lock: %s", __func__, lockfile);
+ PRINT("cannot lock: %s", lockfile);
goto done;
}
if (++tries > 10) {
ret = SSH_ERR_SYSTEM_ERROR;
- PRINT("%s: giving up on: %s", __func__, lockfile);
+ 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, pr)) != 0) {
+ statefile, &have_state, printerror)) != 0) {
if ((r = sshkey_xmss_get_state_from_file((struct sshkey *)k,
- ostatefile, &have_ostate, pr)) == 0) {
+ ostatefile, &have_ostate, printerror)) == 0) {
state->allow_update = 1;
r = sshkey_xmss_forward_state(k, 1);
state->idx = PEEK_U32(k->xmss_sk);
@@ -506,13 +508,13 @@ sshkey_xmss_get_state(const struct sshkey *k, sshkey_printfn *pr)
/* check that bds state is initialized */
if (state->bds.auth == NULL)
goto done;
- PRINT("%s: start from scratch idx 0: %u", __func__, state->idx);
+ PRINT("start from scratch idx 0: %u", state->idx);
} else if (r != 0) {
ret = r;
goto done;
}
if (state->idx + 1 < state->idx) {
- PRINT("%s: state wrap: %u", __func__, state->idx);
+ PRINT("state wrap: %u", state->idx);
goto done;
}
state->have_state = have_state;
@@ -563,7 +565,7 @@ sshkey_xmss_forward_state(const struct sshkey *k, u_int32_t reserve)
}
int
-sshkey_xmss_update_state(const struct sshkey *k, sshkey_printfn *pr)
+sshkey_xmss_update_state(const struct sshkey *k, int printerror)
{
struct ssh_xmss_state *state = k->xmss_state;
struct sshbuf *b = NULL, *enc = NULL;
@@ -587,8 +589,8 @@ sshkey_xmss_update_state(const struct sshkey *k, sshkey_printfn *pr)
ret = 0;
goto done;
} else if (idx != state->idx + 1) {
- PRINT("%s: more than one signature happened: idx %u state %u",
- __func__, idx, state->idx);
+ PRINT("more than one signature happened: idx %u state %u",
+ idx, state->idx);
goto done;
}
state->idx = idx;
@@ -606,55 +608,54 @@ sshkey_xmss_update_state(const struct sshkey *k, sshkey_printfn *pr)
goto done;
}
if ((ret = sshkey_xmss_serialize_state(k, b)) != 0) {
- PRINT("%s: SERLIALIZE FAILED: %d", __func__, ret);
+ PRINT("SERLIALIZE FAILED: %d", ret);
goto done;
}
if ((ret = sshkey_xmss_encrypt_state(k, b, &enc)) != 0) {
- PRINT("%s: ENCRYPT FAILED: %d", __func__, ret);
+ 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("%s: open new state file: %s", __func__, nstatefile);
+ 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("%s: write new state file hdr: %s", __func__, nstatefile);
+ 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("%s: write new state file data: %s", __func__, nstatefile);
+ PRINT("write new state file data: %s", nstatefile);
close(fd);
goto done;
}
if (fsync(fd) == -1) {
ret = SSH_ERR_SYSTEM_ERROR;
- PRINT("%s: sync new state file: %s", __func__, nstatefile);
+ PRINT("sync new state file: %s", nstatefile);
close(fd);
goto done;
}
if (close(fd) == -1) {
ret = SSH_ERR_SYSTEM_ERROR;
- PRINT("%s: close new state file: %s", __func__, nstatefile);
+ 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("%s: backup state %s to %s", __func__, statefile,
- ostatefile);
+ PRINT("backup state %s to %s", statefile, ostatefile);
goto done;
}
}
if (rename(nstatefile, statefile) == -1) {
ret = SSH_ERR_SYSTEM_ERROR;
- PRINT("%s: rename %s to %s", __func__, nstatefile, statefile);
+ PRINT("rename %s to %s", nstatefile, statefile);
goto done;
}
ret = 0;
diff --git a/sshkey-xmss.h b/sshkey-xmss.h
index b9f8ead10..32a12be62 100644
--- a/sshkey-xmss.h
+++ b/sshkey-xmss.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey-xmss.h,v 1.1 2018/02/23 15:58:38 markus Exp $ */
+/* $OpenBSD: sshkey-xmss.h,v 1.3 2021/04/03 06:18:41 djm Exp $ */
/*
* Copyright (c) 2017 Markus Friedl. All rights reserved.
*
@@ -25,10 +25,10 @@
#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
+#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 *);
@@ -37,7 +37,7 @@ void sshkey_xmss_free_state(struct sshkey *);
int sshkey_xmss_generate_private_key(struct sshkey *, u_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);
+ 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 *);
@@ -47,10 +47,10 @@ int sshkey_xmss_deserialize_pk_info(struct sshkey *, struct sshbuf *);
int sshkey_xmss_siglen(const struct sshkey *, size_t *);
void *sshkey_xmss_params(const struct sshkey *);
void *sshkey_xmss_bds_state(const struct sshkey *);
-int sshkey_xmss_get_state(const struct sshkey *, sshkey_printfn *);
+int sshkey_xmss_get_state(const struct sshkey *, int);
int sshkey_xmss_enable_maxsign(struct sshkey *, u_int32_t);
int sshkey_xmss_forward_state(const struct sshkey *, u_int32_t);
-int sshkey_xmss_update_state(const struct sshkey *, sshkey_printfn *);
+int sshkey_xmss_update_state(const struct sshkey *, int);
u_int32_t sshkey_xmss_signatures_left(const struct sshkey *);
#endif /* SSHKEY_XMSS_H */
diff --git a/sshkey.c b/sshkey.c
index e7b464dca..4e356dc39 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.c,v 1.108 2020/04/11 10:16:11 djm Exp $ */
+/* $OpenBSD: sshkey.c,v 1.119 2021/07/23 03:37:52 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
@@ -132,6 +132,8 @@ static const struct keytype keytypes[] = {
# endif /* OPENSSL_HAS_NISTP521 */
{ "sk-ecdsa-sha2-nistp256@openssh.com", "ECDSA-SK", NULL,
KEY_ECDSA_SK, NID_X9_62_prime256v1, 0, 0 },
+ { "webauthn-sk-ecdsa-sha2-nistp256@openssh.com", "ECDSA-SK", NULL,
+ KEY_ECDSA_SK, NID_X9_62_prime256v1, 0, 1 },
# endif /* OPENSSL_HAS_ECC */
{ "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL,
KEY_RSA_CERT, 0, 1, 0 },
@@ -148,7 +150,7 @@ static const struct keytype keytypes[] = {
KEY_ECDSA_CERT, NID_secp384r1, 1, 0 },
# ifdef OPENSSL_HAS_NISTP521
{ "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT", NULL,
- KEY_ECDSA_CERT, NID_secp521r1, 1, 0 },
+ KEY_ECDSA_CERT, NID_secp521r1, 1, 0 },
# endif /* OPENSSL_HAS_NISTP521 */
{ "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-SK-CERT", NULL,
KEY_ECDSA_SK_CERT, NID_X9_62_prime256v1, 1, 0 },
@@ -2033,7 +2035,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)
+ SSHKEY_SERIALIZE_SHIELD)) != 0)
goto out;
/* pad to cipher blocksize */
i = 0;
@@ -2725,7 +2727,7 @@ int
sshkey_sign(struct sshkey *key,
u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen,
- const char *alg, const char *sk_provider, u_int compat)
+ const char *alg, const char *sk_provider, const char *sk_pin, u_int compat)
{
int was_shielded = sshkey_is_shielded(key);
int r2, r = SSH_ERR_INTERNAL_ERROR;
@@ -2764,7 +2766,7 @@ sshkey_sign(struct sshkey *key,
case KEY_ECDSA_SK_CERT:
case KEY_ECDSA_SK:
r = sshsk_sign(sk_provider, key, sigp, lenp, data,
- datalen, compat, /* XXX PIN */ NULL);
+ datalen, compat, sk_pin);
break;
#ifdef WITH_XMSS
case KEY_XMSS:
@@ -2886,7 +2888,8 @@ sshkey_drop_cert(struct sshkey *k)
/* Sign a certified key, (re-)generating the signed certblob. */
int
sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
- const char *sk_provider, sshkey_certify_signer *signer, void *signer_ctx)
+ const char *sk_provider, const char *sk_pin,
+ sshkey_certify_signer *signer, void *signer_ctx)
{
struct sshbuf *principals = NULL;
u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];
@@ -3024,7 +3027,7 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
/* Sign the whole mess */
if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
- sshbuf_len(cert), alg, sk_provider, 0, signer_ctx)) != 0)
+ sshbuf_len(cert), alg, sk_provider, sk_pin, 0, signer_ctx)) != 0)
goto out;
/* Check and update signature_type against what was actually used */
if ((ret = sshkey_get_sigtype(sig_blob, sig_len, &sigtype)) != 0)
@@ -3054,33 +3057,36 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
static int
default_key_sign(struct sshkey *key, u_char **sigp, size_t *lenp,
const u_char *data, size_t datalen,
- const char *alg, const char *sk_provider, u_int compat, void *ctx)
+ const char *alg, const char *sk_provider, const char *sk_pin,
+ u_int compat, void *ctx)
{
if (ctx != NULL)
return SSH_ERR_INVALID_ARGUMENT;
return sshkey_sign(key, sigp, lenp, data, datalen, alg,
- sk_provider, compat);
+ sk_provider, sk_pin, compat);
}
int
sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg,
- const char *sk_provider)
+ const char *sk_provider, const char *sk_pin)
{
- return sshkey_certify_custom(k, ca, alg, sk_provider,
+ return sshkey_certify_custom(k, ca, alg, sk_provider, sk_pin,
default_key_sign, NULL);
}
int
sshkey_cert_check_authority(const struct sshkey *k,
- int want_host, int require_principal,
- const char *name, const char **reason)
+ int want_host, int require_principal, int wildcard_pattern,
+ uint64_t verify_time, const char *name, const char **reason)
{
u_int i, principal_matches;
- time_t now = time(NULL);
if (reason == NULL)
return SSH_ERR_INVALID_ARGUMENT;
-
+ if (!sshkey_is_cert(k)) {
+ *reason = "Key is not a certificate";
+ return SSH_ERR_KEY_CERT_INVALID;
+ }
if (want_host) {
if (k->cert->type != SSH2_CERT_TYPE_HOST) {
*reason = "Certificate invalid: not a host certificate";
@@ -3092,16 +3098,11 @@ sshkey_cert_check_authority(const struct sshkey *k,
return SSH_ERR_KEY_CERT_INVALID;
}
}
- if (now < 0) {
- /* yikes - system clock before epoch! */
+ if (verify_time < k->cert->valid_after) {
*reason = "Certificate invalid: not yet valid";
return SSH_ERR_KEY_CERT_INVALID;
}
- if ((u_int64_t)now < k->cert->valid_after) {
- *reason = "Certificate invalid: not yet valid";
- return SSH_ERR_KEY_CERT_INVALID;
- }
- if ((u_int64_t)now >= k->cert->valid_before) {
+ if (verify_time >= k->cert->valid_before) {
*reason = "Certificate invalid: expired";
return SSH_ERR_KEY_CERT_INVALID;
}
@@ -3113,7 +3114,13 @@ sshkey_cert_check_authority(const struct sshkey *k,
} else if (name != NULL) {
principal_matches = 0;
for (i = 0; i < k->cert->nprincipals; i++) {
- if (strcmp(name, k->cert->principals[i]) == 0) {
+ if (wildcard_pattern) {
+ if (match_pattern(k->cert->principals[i],
+ name)) {
+ principal_matches = 1;
+ break;
+ }
+ } else if (strcmp(name, k->cert->principals[i]) == 0) {
principal_matches = 1;
break;
}
@@ -3127,32 +3134,58 @@ sshkey_cert_check_authority(const struct sshkey *k,
return 0;
}
+int
+sshkey_cert_check_authority_now(const struct sshkey *k,
+ int want_host, int require_principal, int wildcard_pattern,
+ const char *name, const char **reason)
+{
+ time_t now;
+
+ if ((now = time(NULL)) < 0) {
+ /* yikes - system clock before epoch! */
+ *reason = "Certificate invalid: not yet valid";
+ return SSH_ERR_KEY_CERT_INVALID;
+ }
+ return sshkey_cert_check_authority(k, want_host, require_principal,
+ wildcard_pattern, (uint64_t)now, name, reason);
+}
+
+int
+sshkey_cert_check_host(const struct sshkey *key, const char *host,
+ int wildcard_principals, const char *ca_sign_algorithms,
+ const char **reason)
+{
+ int r;
+
+ if ((r = sshkey_cert_check_authority_now(key, 1, 0, wildcard_principals,
+ host, reason)) != 0)
+ return r;
+ if (sshbuf_len(key->cert->critical) != 0) {
+ *reason = "Certificate contains unsupported critical options";
+ return SSH_ERR_KEY_CERT_INVALID;
+ }
+ if (ca_sign_algorithms != NULL &&
+ (r = sshkey_check_cert_sigtype(key, ca_sign_algorithms)) != 0) {
+ *reason = "Certificate signed with disallowed algorithm";
+ return SSH_ERR_KEY_CERT_INVALID;
+ }
+ return 0;
+}
+
size_t
sshkey_format_cert_validity(const struct sshkey_cert *cert, char *s, size_t l)
{
- char from[32], to[32], ret[64];
- time_t tt;
- struct tm *tm;
+ char from[32], to[32], ret[128];
*from = *to = '\0';
if (cert->valid_after == 0 &&
cert->valid_before == 0xffffffffffffffffULL)
return strlcpy(s, "forever", l);
- if (cert->valid_after != 0) {
- /* XXX revisit INT_MAX in 2038 :) */
- tt = cert->valid_after > INT_MAX ?
- INT_MAX : cert->valid_after;
- tm = localtime(&tt);
- strftime(from, sizeof(from), "%Y-%m-%dT%H:%M:%S", tm);
- }
- if (cert->valid_before != 0xffffffffffffffffULL) {
- /* XXX revisit INT_MAX in 2038 :) */
- tt = cert->valid_before > INT_MAX ?
- INT_MAX : cert->valid_before;
- tm = localtime(&tt);
- strftime(to, sizeof(to), "%Y-%m-%dT%H:%M:%S", tm);
- }
+ if (cert->valid_after != 0)
+ format_absolute_time(cert->valid_after, from, sizeof(from));
+ if (cert->valid_before != 0xffffffffffffffffULL)
+ format_absolute_time(cert->valid_before, to, sizeof(to));
if (cert->valid_after == 0)
snprintf(ret, sizeof(ret), "before %s", to);
@@ -3376,10 +3409,12 @@ int
sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
{
char *tname = NULL, *curve = NULL, *xmss_name = NULL;
+ char *expect_sk_application = NULL;
struct sshkey *k = NULL;
size_t pklen = 0, sklen = 0;
int type, r = SSH_ERR_INTERNAL_ERROR;
u_char *ed25519_pk = NULL, *ed25519_sk = NULL;
+ u_char *expect_ed25519_pk = NULL;
u_char *xmss_pk = NULL, *xmss_sk = NULL;
#ifdef WITH_OPENSSL
BIGNUM *exponent = NULL;
@@ -3412,6 +3447,14 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
r = SSH_ERR_KEY_CERT_MISMATCH;
goto out;
}
+ /*
+ * Several fields are redundant between certificate and
+ * private key body, we require these to match.
+ */
+ expect_sk_application = k->sk_application;
+ expect_ed25519_pk = k->ed25519_pk;
+ k->sk_application = NULL;
+ k->ed25519_pk = NULL;
} else {
if ((k = sshkey_new(type)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
@@ -3598,10 +3641,12 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
case KEY_XMSS:
case KEY_XMSS_CERT:
if ((r = sshbuf_get_cstring(buf, &xmss_name, NULL)) != 0 ||
- (r = sshkey_xmss_init(k, xmss_name)) != 0 ||
(r = sshbuf_get_string(buf, &xmss_pk, &pklen)) != 0 ||
(r = sshbuf_get_string(buf, &xmss_sk, &sklen)) != 0)
goto out;
+ if (type == KEY_XMSS &&
+ (r = sshkey_xmss_init(k, xmss_name)) != 0)
+ goto out;
if (pklen != sshkey_xmss_pklen(k) ||
sklen != sshkey_xmss_sklen(k)) {
r = SSH_ERR_INVALID_FORMAT;
@@ -3631,6 +3676,13 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
break;
}
#endif /* WITH_OPENSSL */
+ if ((expect_sk_application != NULL && (k->sk_application == NULL ||
+ strcmp(expect_sk_application, k->sk_application) != 0)) ||
+ (expect_ed25519_pk != NULL && (k->ed25519_pk == NULL ||
+ memcmp(expect_ed25519_pk, k->ed25519_pk, ED25519_PK_SZ) != 0))) {
+ r = SSH_ERR_KEY_CERT_MISMATCH;
+ goto out;
+ }
/* success */
r = 0;
if (kp != NULL) {
@@ -3660,6 +3712,8 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
free(xmss_name);
freezero(xmss_pk, pklen);
freezero(xmss_sk, sklen);
+ free(expect_sk_application);
+ free(expect_ed25519_pk);
return r;
}
@@ -3903,7 +3957,7 @@ sshkey_private_to_blob2(struct sshkey *prv, struct sshbuf *blob,
/* append private key and comment*/
if ((r = sshkey_private_serialize_opt(prv, encrypted,
- SSHKEY_SERIALIZE_FULL)) != 0 ||
+ SSHKEY_SERIALIZE_FULL)) != 0 ||
(r = sshbuf_put_cstring(encrypted, comment)) != 0)
goto out;
@@ -4329,14 +4383,14 @@ sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf,
return SSH_ERR_PASSPHRASE_TOO_SHORT;
if ((blob = sshbuf_new()) == NULL)
return SSH_ERR_ALLOC_FAIL;
- if ((bio = BIO_new(BIO_s_mem())) == NULL) {
+ if ((bio = BIO_new(BIO_s_mem())) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if (format == SSHKEY_PRIVATE_PKCS8 && (pkey = EVP_PKEY_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
- }
+ }
if ((r = sshkey_unshield_private(key)) != 0)
goto out;
@@ -4546,12 +4600,12 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
clear_libcrypto_errors();
if ((pk = PEM_read_bio_PrivateKey(bio, NULL, pem_passphrase_cb,
(char *)passphrase)) == NULL) {
- /*
- * libcrypto may return various ASN.1 errors when attempting
- * to parse a key with an incorrect passphrase.
- * Treat all format errors as "incorrect passphrase" if a
- * passphrase was supplied.
- */
+ /*
+ * libcrypto may return various ASN.1 errors when attempting
+ * to parse a key with an incorrect passphrase.
+ * Treat all format errors as "incorrect passphrase" if a
+ * passphrase was supplied.
+ */
if (passphrase != NULL && *passphrase != '\0')
r = SSH_ERR_KEY_WRONG_PASSPHRASE;
else
@@ -4698,7 +4752,7 @@ sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, int type,
*/
int
sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b,
- u_int32_t maxsign, sshkey_printfn *pr)
+ u_int32_t maxsign, int printerror)
{
int r, rupdate;
@@ -4706,14 +4760,14 @@ sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b,
sshkey_type_plain(k->type) != KEY_XMSS)
return sshkey_private_serialize_opt(k, b,
SSHKEY_SERIALIZE_DEFAULT);
- if ((r = sshkey_xmss_get_state(k, pr)) != 0 ||
+ if ((r = sshkey_xmss_get_state(k, printerror)) != 0 ||
(r = sshkey_private_serialize_opt(k, b,
SSHKEY_SERIALIZE_STATE)) != 0 ||
(r = sshkey_xmss_forward_state(k, maxsign)) != 0)
goto out;
r = 0;
out:
- if ((rupdate = sshkey_xmss_update_state(k, pr)) != 0) {
+ if ((rupdate = sshkey_xmss_update_state(k, printerror)) != 0) {
if (r == 0)
r = rupdate;
}
@@ -4752,7 +4806,7 @@ sshkey_set_filename(struct sshkey *k, const char *filename)
#else
int
sshkey_private_serialize_maxsign(struct sshkey *k, struct sshbuf *b,
- u_int32_t maxsign, sshkey_printfn *pr)
+ u_int32_t maxsign, int printerror)
{
return sshkey_private_serialize_opt(k, b, SSHKEY_SERIALIZE_DEFAULT);
}
diff --git a/sshkey.h b/sshkey.h
index 9c1d4f637..6edc6c5a5 100644
--- a/sshkey.h
+++ b/sshkey.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.h,v 1.45 2020/04/08 00:08:46 djm Exp $ */
+/* $OpenBSD: sshkey.h,v 1.50 2021/07/23 03:37:52 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -39,6 +39,7 @@
# define EC_GROUP void
# define EC_POINT void
# endif /* OPENSSL_HAS_ECC */
+#define SSH_OPENSSL_VERSION OpenSSL_version(OPENSSL_VERSION)
#else /* WITH_OPENSSL */
# define BIGNUM void
# define RSA void
@@ -46,6 +47,7 @@
# define EC_KEY void
# define EC_GROUP void
# define EC_POINT void
+#define SSH_OPENSSL_VERSION "without OpenSSL"
#endif /* WITH_OPENSSL */
#define SSH_RSA_MINIMUM_MODULUS_SIZE 1024
@@ -193,19 +195,24 @@ int sshkey_type_plain(int);
int sshkey_to_certified(struct sshkey *);
int sshkey_drop_cert(struct sshkey *);
int sshkey_cert_copy(const struct sshkey *, struct sshkey *);
-int sshkey_cert_check_authority(const struct sshkey *, int, int,
+int sshkey_cert_check_authority(const struct sshkey *, int, int, int,
+ uint64_t, const char *, const char **);
+int sshkey_cert_check_authority_now(const struct sshkey *, int, int, int,
const char *, const char **);
+int sshkey_cert_check_host(const struct sshkey *, const char *,
+ int , const char *, const char **);
size_t sshkey_format_cert_validity(const struct sshkey_cert *,
char *, size_t) __attribute__((__bounded__(__string__, 2, 3)));
int sshkey_check_cert_sigtype(const struct sshkey *, const char *);
int sshkey_certify(struct sshkey *, struct sshkey *,
- const char *, const char *);
+ const char *, const char *, const char *);
/* Variant allowing use of a custom signature function (e.g. for ssh-agent) */
typedef int sshkey_certify_signer(struct sshkey *, u_char **, size_t *,
- const u_char *, size_t, const char *, const char *, u_int, void *);
+ const u_char *, size_t, const char *, const char *, const char *,
+ u_int, void *);
int sshkey_certify_custom(struct sshkey *, struct sshkey *, const char *,
- const char *, sshkey_certify_signer *, void *);
+ const char *, const char *, sshkey_certify_signer *, void *);
int sshkey_ecdsa_nid_from_name(const char *);
int sshkey_curve_name_to_nid(const char *);
@@ -234,7 +241,7 @@ int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *);
int sshkey_putb_plain(const struct sshkey *, struct sshbuf *);
int sshkey_sign(struct sshkey *, u_char **, size_t *,
- const u_char *, size_t, const char *, const char *, u_int);
+ const u_char *, size_t, const char *, const char *, const char *, u_int);
int sshkey_verify(const struct sshkey *, const u_char *, size_t,
const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **);
int sshkey_check_sigtype(const u_char *, size_t, const char *);
@@ -266,17 +273,12 @@ int sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob,
int ssh_rsa_complete_crt_parameters(struct sshkey *, const BIGNUM *);
/* stateful keys (e.g. XMSS) */
-#ifdef NO_ATTRIBUTE_ON_PROTOTYPE_ARGS
-typedef void sshkey_printfn(const char *, ...);
-#else
-typedef void sshkey_printfn(const char *, ...) __attribute__((format(printf, 1, 2)));
-#endif
int sshkey_set_filename(struct sshkey *, const char *);
int sshkey_enable_maxsign(struct sshkey *, u_int32_t);
u_int32_t sshkey_signatures_left(const struct sshkey *);
-int sshkey_forward_state(const struct sshkey *, u_int32_t, sshkey_printfn *);
-int sshkey_private_serialize_maxsign(struct sshkey *key, struct sshbuf *buf,
- u_int32_t maxsign, sshkey_printfn *pr);
+int sshkey_forward_state(const struct sshkey *, u_int32_t, int);
+int sshkey_private_serialize_maxsign(struct sshkey *key,
+ struct sshbuf *buf, u_int32_t maxsign, int);
void sshkey_sig_details_free(struct sshkey_sig_details *);
diff --git a/sshlogin.c b/sshlogin.c
index 08d2600b2..82dd84819 100644
--- a/sshlogin.c
+++ b/sshlogin.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshlogin.c,v 1.34 2019/06/28 13:35:04 deraadt Exp $ */
+/* $OpenBSD: sshlogin.c,v 1.35 2020/10/18 11:32:02 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -122,7 +122,7 @@ store_lastlog_message(const char *user, uid_t uid)
r = sshbuf_putf(loginmsg, "Last login: %s from %s\r\n",
time_string, hostname);
if (r != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "sshbuf_putf");
}
# endif /* CUSTOM_SYS_AUTH_GET_LASTLOGIN_MSG */
#endif /* NO_SSH_LASTLOG */
diff --git a/sshpty.c b/sshpty.c
index bce09e255..cae0b977a 100644
--- a/sshpty.c
+++ b/sshpty.c
@@ -27,6 +27,7 @@
#endif
#include <pwd.h>
#include <stdarg.h>
+#include <stdio.h>
#include <string.h>
#include <termios.h>
#ifdef HAVE_UTIL_H
diff --git a/sshsig.c b/sshsig.c
index 15f9cead6..d0d401a32 100644
--- a/sshsig.c
+++ b/sshsig.c
@@ -1,3 +1,4 @@
+/* $OpenBSD: sshsig.c,v 1.21 2021/07/23 04:00:59 djm Exp $ */
/*
* Copyright (c) 2019 Google LLC
*
@@ -53,27 +54,26 @@ sshsig_armor(const struct sshbuf *blob, struct sshbuf **out)
*out = NULL;
if ((buf = sshbuf_new()) == NULL) {
- error("%s: sshbuf_new failed", __func__);
+ error_f("sshbuf_new failed");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
if ((r = sshbuf_put(buf, BEGIN_SIGNATURE,
sizeof(BEGIN_SIGNATURE)-1)) != 0) {
- error("%s: sshbuf_putf failed: %s", __func__, ssh_err(r));
+ error_fr(r, "sshbuf_putf");
goto out;
}
if ((r = sshbuf_dtob64(blob, buf, 1)) != 0) {
- error("%s: Couldn't base64 encode signature blob: %s",
- __func__, ssh_err(r));
+ error_fr(r, "base64 encode signature");
goto out;
}
if ((r = sshbuf_put(buf, END_SIGNATURE,
sizeof(END_SIGNATURE)-1)) != 0 ||
(r = sshbuf_put_u8(buf, '\n')) != 0) {
- error("%s: sshbuf_put failed: %s", __func__, ssh_err(r));
+ error_fr(r, "sshbuf_put");
goto out;
}
/* success */
@@ -95,7 +95,7 @@ sshsig_dearmor(struct sshbuf *sig, struct sshbuf **out)
char *b64 = NULL;
if ((sbuf = sshbuf_fromb(sig)) == NULL) {
- error("%s: sshbuf_fromb failed", __func__);
+ error_f("sshbuf_fromb failed");
return SSH_ERR_ALLOC_FAIL;
}
@@ -106,7 +106,7 @@ sshsig_dearmor(struct sshbuf *sig, struct sshbuf **out)
}
if ((r = sshbuf_consume(sbuf, sizeof(BEGIN_SIGNATURE)-1)) != 0) {
- error("%s: sshbuf_consume failed: %s", __func__, ssh_err(r));
+ error_fr(r, "consume");
goto done;
}
@@ -117,24 +117,24 @@ sshsig_dearmor(struct sshbuf *sig, struct sshbuf **out)
}
if ((r = sshbuf_consume_end(sbuf, sshbuf_len(sbuf)-eoffset)) != 0) {
- error("%s: sshbuf_consume failed: %s", __func__, ssh_err(r));
+ error_fr(r, "consume");
goto done;
}
if ((b64 = sshbuf_dup_string(sbuf)) == NULL) {
- error("%s: sshbuf_dup_string failed", __func__);
+ error_f("sshbuf_dup_string failed");
r = SSH_ERR_ALLOC_FAIL;
goto done;
}
if ((buf = sshbuf_new()) == NULL) {
- error("%s: sshbuf_new() failed", __func__);
+ error_f("sshbuf_new() failed");
r = SSH_ERR_ALLOC_FAIL;
goto done;
}
if ((r = sshbuf_b64tod(buf, b64)) != 0) {
- error("Couldn't decode signature: %s", ssh_err(r));
+ error_fr(r, "decode base64");
goto done;
}
@@ -151,7 +151,7 @@ done:
static int
sshsig_wrap_sign(struct sshkey *key, const char *hashalg,
- const char *sk_provider, const struct sshbuf *h_message,
+ const char *sk_provider, const char *sk_pin, const struct sshbuf *h_message,
const char *sig_namespace, struct sshbuf **out,
sshsig_signer *signer, void *signer_ctx)
{
@@ -164,7 +164,7 @@ sshsig_wrap_sign(struct sshkey *key, const char *hashalg,
if ((tosign = sshbuf_new()) == NULL ||
(blob = sshbuf_new()) == NULL) {
- error("%s: sshbuf_new failed", __func__);
+ error_f("sshbuf_new failed");
r = SSH_ERR_ALLOC_FAIL;
goto done;
}
@@ -174,7 +174,7 @@ sshsig_wrap_sign(struct sshkey *key, const char *hashalg,
(r = sshbuf_put_string(tosign, NULL, 0)) != 0 || /* reserved */
(r = sshbuf_put_cstring(tosign, hashalg)) != 0 ||
(r = sshbuf_put_stringb(tosign, h_message)) != 0) {
- error("Couldn't construct message to sign: %s", ssh_err(r));
+ error_fr(r, "assemble message to sign");
goto done;
}
@@ -185,15 +185,15 @@ sshsig_wrap_sign(struct sshkey *key, const char *hashalg,
if (signer != NULL) {
if ((r = signer(key, &sig, &slen,
sshbuf_ptr(tosign), sshbuf_len(tosign),
- sign_alg, sk_provider, 0, signer_ctx)) != 0) {
- error("Couldn't sign message: %s", ssh_err(r));
+ sign_alg, sk_provider, sk_pin, 0, signer_ctx)) != 0) {
+ error_r(r, "Couldn't sign message (signer)");
goto done;
}
} else {
if ((r = sshkey_sign(key, &sig, &slen,
sshbuf_ptr(tosign), sshbuf_len(tosign),
- sign_alg, sk_provider, 0)) != 0) {
- error("Couldn't sign message: %s", ssh_err(r));
+ sign_alg, sk_provider, sk_pin, 0)) != 0) {
+ error_r(r, "Couldn't sign message");
goto done;
}
}
@@ -205,7 +205,7 @@ sshsig_wrap_sign(struct sshkey *key, const char *hashalg,
(r = sshbuf_put_string(blob, NULL, 0)) != 0 || /* reserved */
(r = sshbuf_put_cstring(blob, hashalg)) != 0 ||
(r = sshbuf_put_string(blob, sig, slen)) != 0) {
- error("Couldn't populate blob: %s", ssh_err(r));
+ error_fr(r, "assemble signature object");
goto done;
}
@@ -249,7 +249,7 @@ sshsig_check_hashalg(const char *hashalg)
if (hashalg == NULL ||
match_pattern_list(hashalg, HASHALG_ALLOWED, 0) == 1)
return 0;
- error("%s: unsupported hash algorithm \"%.100s\"", __func__, hashalg);
+ error_f("unsupported hash algorithm \"%.100s\"", hashalg);
return SSH_ERR_SIGN_ALG_UNSUPPORTED;
}
@@ -271,7 +271,7 @@ sshsig_peek_hashalg(struct sshbuf *signature, char **hashalgp)
(r = sshbuf_get_string(buf, NULL, NULL)) != 0 ||
(r = sshbuf_get_cstring(buf, &hashalg, NULL)) != 0 ||
(r = sshbuf_get_string_direct(buf, NULL, NULL)) != 0) {
- error("Couldn't parse signature blob: %s", ssh_err(r));
+ error_fr(r, "parse signature object");
goto done;
}
@@ -297,14 +297,14 @@ sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg,
char *got_namespace = NULL, *sigtype = NULL, *sig_hashalg = NULL;
size_t siglen;
- debug("%s: verify message length %zu", __func__, sshbuf_len(h_message));
+ debug_f("verify message length %zu", sshbuf_len(h_message));
if (sig_details != NULL)
*sig_details = NULL;
if (sign_keyp != NULL)
*sign_keyp = NULL;
if ((toverify = sshbuf_new()) == NULL) {
- error("%s: sshbuf_new failed", __func__);
+ error_f("sshbuf_new failed");
r = SSH_ERR_ALLOC_FAIL;
goto done;
}
@@ -314,7 +314,7 @@ sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg,
(r = sshbuf_put_string(toverify, NULL, 0)) != 0 || /* reserved */
(r = sshbuf_put_cstring(toverify, hashalg)) != 0 ||
(r = sshbuf_put_stringb(toverify, h_message)) != 0) {
- error("Couldn't construct message to verify: %s", ssh_err(r));
+ error_fr(r, "assemble message to verify");
goto done;
}
@@ -326,7 +326,7 @@ sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg,
(r = sshbuf_get_string(signature, NULL, NULL)) != 0 ||
(r = sshbuf_get_cstring(signature, &sig_hashalg, NULL)) != 0 ||
(r = sshbuf_get_string_direct(signature, &sig, &siglen)) != 0) {
- error("Couldn't parse signature blob: %s", ssh_err(r));
+ error_fr(r, "parse signature object");
goto done;
}
@@ -338,23 +338,23 @@ sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg,
if (strcmp(expect_namespace, got_namespace) != 0) {
error("Couldn't verify signature: namespace does not match");
- debug("%s: expected namespace \"%s\" received \"%s\"",
- __func__, expect_namespace, got_namespace);
+ debug_f("expected namespace \"%s\" received \"%s\"",
+ expect_namespace, got_namespace);
r = SSH_ERR_SIGNATURE_INVALID;
goto done;
}
if (strcmp(hashalg, sig_hashalg) != 0) {
error("Couldn't verify signature: hash algorithm mismatch");
- debug("%s: expected algorithm \"%s\" received \"%s\"",
- __func__, hashalg, sig_hashalg);
+ debug_f("expected algorithm \"%s\" received \"%s\"",
+ hashalg, sig_hashalg);
r = SSH_ERR_SIGNATURE_INVALID;
goto done;
}
/* Ensure that RSA keys use an acceptable signature algorithm */
if (sshkey_type_plain(key->type) == KEY_RSA) {
if ((r = sshkey_get_sigtype(sig, siglen, &sigtype)) != 0) {
- error("Couldn't verify signature: unable to get "
- "signature type: %s", ssh_err(r));
+ error_r(r, "Couldn't verify signature: unable to get "
+ "signature type");
goto done;
}
if (match_pattern_list(sigtype, RSA_SIGN_ALLOWED, 0) != 1) {
@@ -366,7 +366,7 @@ sshsig_wrap_verify(struct sshbuf *signature, const char *hashalg,
}
if ((r = sshkey_verify(key, sig, siglen, sshbuf_ptr(toverify),
sshbuf_len(toverify), NULL, 0, sig_details)) != 0) {
- error("Signature verification failed: %s", ssh_err(r));
+ error_r(r, "Signature verification failed");
goto done;
}
@@ -399,16 +399,15 @@ hash_buffer(const struct sshbuf *m, const char *hashalg, struct sshbuf **bp)
if ((r = sshsig_check_hashalg(hashalg)) != 0)
return r;
if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) {
- error("%s: can't look up hash algorithm %s",
- __func__, hashalg);
+ error_f("can't look up hash algorithm %s", hashalg);
return SSH_ERR_INTERNAL_ERROR;
}
if ((r = ssh_digest_buffer(alg, m, hash, sizeof(hash))) != 0) {
- error("%s: ssh_digest_buffer failed: %s", __func__, ssh_err(r));
+ error_fr(r, "ssh_digest_buffer");
return r;
}
if ((hex = tohex(hash, ssh_digest_bytes(alg))) != NULL) {
- debug3("%s: final hash: %s", __func__, hex);
+ debug3_f("final hash: %s", hex);
freezero(hex, strlen(hex));
}
if ((b = sshbuf_new()) == NULL) {
@@ -416,7 +415,7 @@ hash_buffer(const struct sshbuf *m, const char *hashalg, struct sshbuf **bp)
goto out;
}
if ((r = sshbuf_put(b, hash, ssh_digest_bytes(alg))) != 0) {
- error("%s: sshbuf_put: %s", __func__, ssh_err(r));
+ error_fr(r, "sshbuf_put");
goto out;
}
*bp = b;
@@ -430,7 +429,8 @@ hash_buffer(const struct sshbuf *m, const char *hashalg, struct sshbuf **bp)
}
int
-sshsig_signb(struct sshkey *key, const char *hashalg, const char *sk_provider,
+sshsig_signb(struct sshkey *key, const char *hashalg,
+ const char *sk_provider, const char *sk_pin,
const struct sshbuf *message, const char *sig_namespace,
struct sshbuf **out, sshsig_signer *signer, void *signer_ctx)
{
@@ -442,10 +442,10 @@ sshsig_signb(struct sshkey *key, const char *hashalg, const char *sk_provider,
if (out != NULL)
*out = NULL;
if ((r = hash_buffer(message, hashalg, &b)) != 0) {
- error("%s: hash_buffer failed: %s", __func__, ssh_err(r));
+ error_fr(r, "hash buffer");
goto out;
}
- if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, b,
+ if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, sk_pin, b,
sig_namespace, out, signer, signer_ctx)) != 0)
goto out;
/* success */
@@ -470,9 +470,9 @@ sshsig_verifyb(struct sshbuf *signature, const struct sshbuf *message,
*sign_keyp = NULL;
if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0)
return r;
- debug("%s: signature made with hash \"%s\"", __func__, hashalg);
+ debug_f("signature made with hash \"%s\"", hashalg);
if ((r = hash_buffer(message, hashalg, &b)) != 0) {
- error("%s: hash_buffer failed: %s", __func__, ssh_err(r));
+ error_fr(r, "hash buffer");
goto out;
}
if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace,
@@ -501,12 +501,11 @@ hash_file(int fd, const char *hashalg, struct sshbuf **bp)
if ((r = sshsig_check_hashalg(hashalg)) != 0)
return r;
if ((alg = ssh_digest_alg_by_name(hashalg)) == -1) {
- error("%s: can't look up hash algorithm %s",
- __func__, hashalg);
+ error_f("can't look up hash algorithm %s", hashalg);
return SSH_ERR_INTERNAL_ERROR;
}
if ((ctx = ssh_digest_start(alg)) == NULL) {
- error("%s: ssh_digest_start failed", __func__);
+ error_f("ssh_digest_start failed");
return SSH_ERR_INTERNAL_ERROR;
}
for (;;) {
@@ -514,28 +513,27 @@ hash_file(int fd, const char *hashalg, struct sshbuf **bp)
if (errno == EINTR || errno == EAGAIN)
continue;
oerrno = errno;
- error("%s: read: %s", __func__, strerror(errno));
+ error_f("read: %s", strerror(errno));
ssh_digest_free(ctx);
errno = oerrno;
r = SSH_ERR_SYSTEM_ERROR;
goto out;
} else if (n == 0) {
- debug2("%s: hashed %zu bytes", __func__, total);
+ debug2_f("hashed %zu bytes", total);
break; /* EOF */
}
total += (size_t)n;
if ((r = ssh_digest_update(ctx, rbuf, (size_t)n)) != 0) {
- error("%s: ssh_digest_update: %s",
- __func__, ssh_err(r));
+ error_fr(r, "ssh_digest_update");
goto out;
}
}
if ((r = ssh_digest_final(ctx, hash, sizeof(hash))) != 0) {
- error("%s: ssh_digest_final: %s", __func__, ssh_err(r));
+ error_fr(r, "ssh_digest_final");
goto out;
}
if ((hex = tohex(hash, ssh_digest_bytes(alg))) != NULL) {
- debug3("%s: final hash: %s", __func__, hex);
+ debug3_f("final hash: %s", hex);
freezero(hex, strlen(hex));
}
if ((b = sshbuf_new()) == NULL) {
@@ -543,7 +541,7 @@ hash_file(int fd, const char *hashalg, struct sshbuf **bp)
goto out;
}
if ((r = sshbuf_put(b, hash, ssh_digest_bytes(alg))) != 0) {
- error("%s: sshbuf_put: %s", __func__, ssh_err(r));
+ error_fr(r, "sshbuf_put");
goto out;
}
*bp = b;
@@ -558,7 +556,8 @@ hash_file(int fd, const char *hashalg, struct sshbuf **bp)
}
int
-sshsig_sign_fd(struct sshkey *key, const char *hashalg, const char *sk_provider,
+sshsig_sign_fd(struct sshkey *key, const char *hashalg,
+ const char *sk_provider, const char *sk_pin,
int fd, const char *sig_namespace, struct sshbuf **out,
sshsig_signer *signer, void *signer_ctx)
{
@@ -570,10 +569,10 @@ sshsig_sign_fd(struct sshkey *key, const char *hashalg, const char *sk_provider,
if (out != NULL)
*out = NULL;
if ((r = hash_file(fd, hashalg, &b)) != 0) {
- error("%s: hash_file failed: %s", __func__, ssh_err(r));
+ error_fr(r, "hash_file");
return r;
}
- if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, b,
+ if ((r = sshsig_wrap_sign(key, hashalg, sk_provider, sk_pin, b,
sig_namespace, out, signer, signer_ctx)) != 0)
goto out;
/* success */
@@ -598,9 +597,9 @@ sshsig_verify_fd(struct sshbuf *signature, int fd,
*sign_keyp = NULL;
if ((r = sshsig_peek_hashalg(signature, &hashalg)) != 0)
return r;
- debug("%s: signature made with hash \"%s\"", __func__, hashalg);
+ debug_f("signature made with hash \"%s\"", hashalg);
if ((r = hash_file(fd, hashalg, &b)) != 0) {
- error("%s: hash_file failed: %s", __func__, ssh_err(r));
+ error_fr(r, "hash_file");
goto out;
}
if ((r = sshsig_wrap_verify(signature, hashalg, b, expect_namespace,
@@ -617,6 +616,7 @@ sshsig_verify_fd(struct sshbuf *signature, int fd,
struct sshsigopt {
int ca;
char *namespaces;
+ uint64_t valid_after, valid_before;
};
struct sshsigopt *
@@ -625,6 +625,7 @@ sshsigopt_parse(const char *opts, const char *path, u_long linenum,
{
struct sshsigopt *ret;
int r;
+ char *opt;
const char *errstr = NULL;
if ((ret = calloc(1, sizeof(*ret))) == NULL)
@@ -644,6 +645,34 @@ sshsigopt_parse(const char *opts, const char *path, u_long linenum,
ret->namespaces = opt_dequote(&opts, &errstr);
if (ret->namespaces == NULL)
goto fail;
+ } else if (opt_match(&opts, "valid-after")) {
+ if (ret->valid_after != 0) {
+ errstr = "multiple \"valid-after\" clauses";
+ goto fail;
+ }
+ if ((opt = opt_dequote(&opts, &errstr)) == NULL)
+ goto fail;
+ if (parse_absolute_time(opt, &ret->valid_after) != 0 ||
+ ret->valid_after == 0) {
+ free(opt);
+ errstr = "invalid \"valid-after\" time";
+ goto fail;
+ }
+ free(opt);
+ } else if (opt_match(&opts, "valid-before")) {
+ if (ret->valid_before != 0) {
+ errstr = "multiple \"valid-before\" clauses";
+ goto fail;
+ }
+ if ((opt = opt_dequote(&opts, &errstr)) == NULL)
+ goto fail;
+ if (parse_absolute_time(opt, &ret->valid_before) != 0 ||
+ ret->valid_before == 0) {
+ free(opt);
+ errstr = "invalid \"valid-before\" time";
+ goto fail;
+ }
+ free(opt);
}
/*
* Skip the comma, and move to the next option
@@ -662,6 +691,12 @@ sshsigopt_parse(const char *opts, const char *path, u_long linenum,
goto fail;
}
}
+ /* final consistency check */
+ if (ret->valid_after != 0 && ret->valid_before != 0 &&
+ ret->valid_before <= ret->valid_after) {
+ errstr = "\"valid-before\" time is before \"valid-after\"";
+ goto fail;
+ }
/* success */
return ret;
fail:
@@ -710,7 +745,7 @@ parse_principals_key_and_options(const char *path, u_long linenum, char *line,
goto out;
}
if ((principals = strdup(tmp)) == NULL) {
- error("%s: strdup failed", __func__);
+ error_f("strdup failed");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
@@ -725,12 +760,12 @@ parse_principals_key_and_options(const char *path, u_long linenum, char *line,
r = SSH_ERR_KEY_NOT_FOUND;
goto out;
}
- debug("%s: %s:%lu: matched principal \"%s\"",
- __func__, path, linenum, required_principal);
+ debug_f("%s:%lu: matched principal \"%s\"",
+ path, linenum, required_principal);
}
if ((key = sshkey_new(KEY_UNSPEC)) == NULL) {
- error("%s: sshkey_new failed", __func__);
+ error_f("sshkey_new failed");
r = SSH_ERR_ALLOC_FAIL;
goto out;
}
@@ -780,12 +815,13 @@ parse_principals_key_and_options(const char *path, u_long linenum, char *line,
static int
check_allowed_keys_line(const char *path, u_long linenum, char *line,
const struct sshkey *sign_key, const char *principal,
- const char *sig_namespace)
+ const char *sig_namespace, uint64_t verify_time)
{
struct sshkey *found_key = NULL;
- int r, found = 0;
+ int r, success = 0;
const char *reason = NULL;
struct sshsigopt *sigopts = NULL;
+ char tvalid[64], tverify[64];
/* Parse the line */
if ((r = parse_principals_key_and_options(path, linenum, line,
@@ -794,44 +830,63 @@ check_allowed_keys_line(const char *path, u_long linenum, char *line,
goto done;
}
- /* Check whether options preclude the use of this key */
- if (sigopts->namespaces != NULL &&
- match_pattern_list(sig_namespace, sigopts->namespaces, 0) != 1) {
- error("%s:%lu: key is not permitted for use in signature "
- "namespace \"%s\"", path, linenum, sig_namespace);
- goto done;
- }
-
if (!sigopts->ca && sshkey_equal(found_key, sign_key)) {
/* Exact match of key */
- debug("%s:%lu: matched key and principal", path, linenum);
- /* success */
- found = 1;
+ debug("%s:%lu: matched key", path, linenum);
} else if (sigopts->ca && sshkey_is_cert(sign_key) &&
sshkey_equal_public(sign_key->cert->signature_key, found_key)) {
/* Match of certificate's CA key */
- if ((r = sshkey_cert_check_authority(sign_key, 0, 1,
- principal, &reason)) != 0) {
+ if ((r = sshkey_cert_check_authority(sign_key, 0, 1, 0,
+ verify_time, principal, &reason)) != 0) {
error("%s:%lu: certificate not authorized: %s",
path, linenum, reason);
goto done;
}
debug("%s:%lu: matched certificate CA key", path, linenum);
- /* success */
- found = 1;
} else {
- /* Principal matched but key didn't */
+ /* Didn't match key */
+ goto done;
+ }
+
+ /* Check whether options preclude the use of this key */
+ if (sigopts->namespaces != NULL &&
+ match_pattern_list(sig_namespace, sigopts->namespaces, 0) != 1) {
+ error("%s:%lu: key is not permitted for use in signature "
+ "namespace \"%s\"", path, linenum, sig_namespace);
+ goto done;
+ }
+
+ /* check key time validity */
+ format_absolute_time((uint64_t)verify_time, tverify, sizeof(tverify));
+ if (sigopts->valid_after != 0 &&
+ (uint64_t)verify_time < sigopts->valid_after) {
+ format_absolute_time(sigopts->valid_after,
+ tvalid, sizeof(tvalid));
+ error("%s:%lu: key is not yet valid: "
+ "verify time %s < valid-after %s", path, linenum,
+ tverify, tvalid);
goto done;
}
+ if (sigopts->valid_before != 0 &&
+ (uint64_t)verify_time > sigopts->valid_before) {
+ format_absolute_time(sigopts->valid_before,
+ tvalid, sizeof(tvalid));
+ error("%s:%lu: key has expired: "
+ "verify time %s > valid-before %s", path, linenum,
+ tverify, tvalid);
+ goto done;
+ }
+ success = 1;
+
done:
sshkey_free(found_key);
sshsigopt_free(sigopts);
- return found ? 0 : SSH_ERR_KEY_NOT_FOUND;
+ return success ? 0 : SSH_ERR_KEY_NOT_FOUND;
}
int
sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key,
- const char *principal, const char *sig_namespace)
+ const char *principal, const char *sig_namespace, uint64_t verify_time)
{
FILE *f = NULL;
char *line = NULL;
@@ -851,9 +906,10 @@ sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key,
while (getline(&line, &linesize, f) != -1) {
linenum++;
r = check_allowed_keys_line(path, linenum, line, sign_key,
- principal, sig_namespace);
+ principal, sig_namespace, verify_time);
free(line);
line = NULL;
+ linesize = 0;
if (r == SSH_ERR_KEY_NOT_FOUND)
continue;
else if (r == 0) {
@@ -871,7 +927,7 @@ sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key,
static int
cert_filter_principals(const char *path, u_long linenum,
- char **principalsp, const struct sshkey *cert)
+ char **principalsp, const struct sshkey *cert, uint64_t verify_time)
{
char *cp, *oprincipals, *principals;
const char *reason;
@@ -893,15 +949,15 @@ cert_filter_principals(const char *path, u_long linenum,
continue;
}
/* Check against principals list in certificate */
- if ((r = sshkey_cert_check_authority(cert, 0, 1,
- cp, &reason)) != 0) {
+ if ((r = sshkey_cert_check_authority(cert, 0, 1, 0,
+ verify_time, cp, &reason)) != 0) {
debug("%s:%lu: principal \"%s\" not authorized: %s",
path, linenum, cp, reason);
continue;
}
if ((r = sshbuf_putf(nprincipals, "%s%s",
sshbuf_len(nprincipals) != 0 ? "," : "", cp)) != 0) {
- error("%s: buffer error", __func__);
+ error_f("buffer error");
goto out;
}
}
@@ -911,7 +967,7 @@ cert_filter_principals(const char *path, u_long linenum,
goto out;
}
if ((principals = sshbuf_dup_string(nprincipals)) == NULL) {
- error("%s: buffer error", __func__);
+ error_f("buffer error");
goto out;
}
/* success */
@@ -925,7 +981,7 @@ cert_filter_principals(const char *path, u_long linenum,
static int
get_matching_principals_from_line(const char *path, u_long linenum, char *line,
- const struct sshkey *sign_key, char **principalsp)
+ const struct sshkey *sign_key, uint64_t verify_time, char **principalsp)
{
struct sshkey *found_key = NULL;
char *principals = NULL;
@@ -951,10 +1007,10 @@ get_matching_principals_from_line(const char *path, u_long linenum, char *line,
sshkey_equal_public(sign_key->cert->signature_key, found_key)) {
/* Remove principals listed in file but not allowed by cert */
if ((r = cert_filter_principals(path, linenum,
- &principals, sign_key)) != 0) {
+ &principals, sign_key, verify_time)) != 0) {
/* error already displayed */
- debug("%s:%lu: cert_filter_principals: %s",
- path, linenum, ssh_err(r));
+ debug_r(r, "%s:%lu: cert_filter_principals",
+ path, linenum);
goto done;
}
debug("%s:%lu: matched certificate CA key", path, linenum);
@@ -977,7 +1033,7 @@ get_matching_principals_from_line(const char *path, u_long linenum, char *line,
int
sshsig_find_principals(const char *path, const struct sshkey *sign_key,
- char **principals)
+ uint64_t verify_time, char **principals)
{
FILE *f = NULL;
char *line = NULL;
@@ -996,9 +1052,10 @@ sshsig_find_principals(const char *path, const struct sshkey *sign_key,
while (getline(&line, &linesize, f) != -1) {
linenum++;
r = get_matching_principals_from_line(path, linenum, line,
- sign_key, principals);
+ sign_key, verify_time, principals);
free(line);
line = NULL;
+ linesize = 0;
if (r == SSH_ERR_KEY_NOT_FOUND)
continue;
else if (r == 0) {
diff --git a/sshsig.h b/sshsig.h
index 63cc1ad1a..b725c7d7a 100644
--- a/sshsig.h
+++ b/sshsig.h
@@ -1,3 +1,4 @@
+/* $OpenBSD: sshsig.h,v 1.10 2021/07/23 03:37:52 djm Exp $ */
/*
* Copyright (c) 2019 Google LLC
*
@@ -23,7 +24,8 @@ struct sshsigopt;
struct sshkey_sig_details;
typedef int sshsig_signer(struct sshkey *, u_char **, size_t *,
- const u_char *, size_t, const char *, const char *, u_int, void *);
+ const u_char *, size_t, const char *, const char *, const char *,
+ u_int, void *);
/* Buffer-oriented API */
@@ -33,7 +35,7 @@ typedef int sshsig_signer(struct sshkey *, u_char **, size_t *,
* out is populated with the detached signature, or NULL on failure.
*/
int sshsig_signb(struct sshkey *key, const char *hashalg,
- const char *sk_provider, const struct sshbuf *message,
+ const char *sk_provider, const char *sk_pin, const struct sshbuf *message,
const char *sig_namespace, struct sshbuf **out,
sshsig_signer *signer, void *signer_ctx);
@@ -54,7 +56,8 @@ int sshsig_verifyb(struct sshbuf *signature,
* out is populated with the detached signature, or NULL on failure.
*/
int sshsig_sign_fd(struct sshkey *key, const char *hashalg,
- const char *sk_provider, int fd, const char *sig_namespace,
+ const char *sk_provider, const char *sk_pin,
+ int fd, const char *sig_namespace,
struct sshbuf **out, sshsig_signer *signer, void *signer_ctx);
/*
@@ -83,7 +86,7 @@ int sshsig_dearmor(struct sshbuf *sig, struct sshbuf **out);
* an allowed_keys file. Returns 0 on success.
*/
int sshsig_check_allowed_keys(const char *path, const struct sshkey *sign_key,
- const char *principal, const char *ns);
+ const char *principal, const char *ns, uint64_t verify_time);
/* Parse zero or more allowed_keys signature options */
struct sshsigopt *sshsigopt_parse(const char *opts,
@@ -99,6 +102,6 @@ int sshsig_get_pubkey(struct sshbuf *signature, struct sshkey **pubkey);
* 0 on success.
*/
int sshsig_find_principals(const char *path, const struct sshkey *sign_key,
- char **principal);
+ uint64_t verify_time, char **principal);
#endif /* SSHSIG_H */
diff --git a/ttymodes.c b/ttymodes.c
index f0c2a5d37..1d20ce800 100644
--- a/ttymodes.c
+++ b/ttymodes.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ttymodes.c,v 1.34 2018/07/09 21:20:26 markus Exp $ */
+/* $OpenBSD: ttymodes.c,v 1.36 2021/01/27 09:26:54 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -283,11 +283,11 @@ ssh_tty_make_modes(struct ssh *ssh, int fd, struct termios *tiop)
int r, ibaud, obaud;
if ((buf = sshbuf_new()) == NULL)
- fatal("%s: sshbuf_new failed", __func__);
+ fatal_f("sshbuf_new failed");
if (tiop == NULL) {
if (fd == -1) {
- debug("%s: no fd or tio", __func__);
+ debug_f("no fd or tio");
goto end;
}
if (tcgetattr(fd, &tio) == -1) {
@@ -304,23 +304,23 @@ ssh_tty_make_modes(struct ssh *ssh, int fd, struct termios *tiop)
(r = sshbuf_put_u32(buf, obaud)) != 0 ||
(r = sshbuf_put_u8(buf, TTY_OP_ISPEED)) != 0 ||
(r = sshbuf_put_u32(buf, ibaud)) != 0)
- fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose");
/* Store values of mode flags. */
#define TTYCHAR(NAME, OP) \
if ((r = sshbuf_put_u8(buf, OP)) != 0 || \
(r = sshbuf_put_u32(buf, \
special_char_encode(tio.c_cc[NAME]))) != 0) \
- fatal("%s: buffer error: %s", __func__, ssh_err(r)); \
+ fatal_fr(r, "compose %s", #NAME);
#define SSH_TTYMODE_IUTF8 42 /* for SSH_BUG_UTF8TTYMODE */
#define TTYMODE(NAME, FIELD, OP) \
- if (OP == SSH_TTYMODE_IUTF8 && (datafellows & SSH_BUG_UTF8TTYMODE)) { \
- debug3("%s: SSH_BUG_UTF8TTYMODE", __func__); \
+ if (OP == SSH_TTYMODE_IUTF8 && (ssh->compat & SSH_BUG_UTF8TTYMODE)) { \
+ debug3_f("SSH_BUG_UTF8TTYMODE"); \
} else if ((r = sshbuf_put_u8(buf, OP)) != 0 || \
(r = sshbuf_put_u32(buf, ((tio.FIELD & NAME) != 0))) != 0) \
- fatal("%s: buffer error: %s", __func__, ssh_err(r)); \
+ fatal_fr(r, "compose %s", #NAME);
#include "ttymodes.h"
@@ -331,7 +331,7 @@ end:
/* Mark end of mode data. */
if ((r = sshbuf_put_u8(buf, TTY_OP_END)) != 0 ||
(r = sshpkt_put_stringb(ssh, buf)) != 0)
- fatal("%s: packet error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "compose end");
sshbuf_free(buf);
}
@@ -351,11 +351,11 @@ ssh_tty_parse_modes(struct ssh *ssh, int fd)
size_t len;
if ((r = sshpkt_get_string_direct(ssh, &data, &len)) != 0)
- fatal("%s: packet error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse");
if (len == 0)
return;
if ((buf = sshbuf_from(data, len)) == NULL) {
- error("%s: sshbuf_from failed", __func__);
+ error_f("sshbuf_from failed");
return;
}
@@ -371,15 +371,14 @@ ssh_tty_parse_modes(struct ssh *ssh, int fd)
while (sshbuf_len(buf) > 0) {
if ((r = sshbuf_get_u8(buf, &opcode)) != 0)
- fatal("%s: packet error: %s", __func__, ssh_err(r));
+ fatal_fr(r, "parse opcode");
switch (opcode) {
case TTY_OP_END:
goto set;
case TTY_OP_ISPEED:
if ((r = sshbuf_get_u32(buf, &baud)) != 0)
- fatal("%s: packet error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "parse ispeed");
if (failure != -1 &&
cfsetispeed(&tio, baud_to_speed(baud)) == -1)
error("cfsetispeed failed for %d", baud);
@@ -387,8 +386,7 @@ ssh_tty_parse_modes(struct ssh *ssh, int fd)
case TTY_OP_OSPEED:
if ((r = sshbuf_get_u32(buf, &baud)) != 0)
- fatal("%s: packet error: %s",
- __func__, ssh_err(r));
+ fatal_fr(r, "parse ospeed");
if (failure != -1 &&
cfsetospeed(&tio, baud_to_speed(baud)) == -1)
error("cfsetospeed failed for %d", baud);
@@ -397,15 +395,13 @@ ssh_tty_parse_modes(struct ssh *ssh, int fd)
#define TTYCHAR(NAME, OP) \
case OP: \
if ((r = sshbuf_get_u32(buf, &u)) != 0) \
- fatal("%s: packet error: %s", __func__, \
- ssh_err(r)); \
+ fatal_fr(r, "parse %s", #NAME); \
tio.c_cc[NAME] = special_char_decode(u); \
break;
#define TTYMODE(NAME, FIELD, OP) \
case OP: \
if ((r = sshbuf_get_u32(buf, &u)) != 0) \
- fatal("%s: packet error: %s", __func__, \
- ssh_err(r)); \
+ fatal_fr(r, "parse %s", #NAME); \
if (u) \
tio.FIELD |= NAME; \
else \
@@ -429,12 +425,10 @@ ssh_tty_parse_modes(struct ssh *ssh, int fd)
*/
if (opcode > 0 && opcode < 160) {
if ((r = sshbuf_get_u32(buf, NULL)) != 0)
- fatal("%s: packet error: %s", __func__,
- ssh_err(r));
+ fatal_fr(r, "parse arg");
break;
} else {
- logit("%s: unknown opcode %d", __func__,
- opcode);
+ logit_f("unknown opcode %d", opcode);
goto set;
}
}
@@ -444,7 +438,7 @@ set:
len = sshbuf_len(buf);
sshbuf_free(buf);
if (len > 0) {
- logit("%s: %zu bytes left", __func__, len);
+ logit_f("%zu bytes left", len);
return; /* Don't process bytes passed */
}
if (failure == -1)
diff --git a/uidswap.c b/uidswap.c
index 285c5aaea..d373859ff 100644
--- a/uidswap.c
+++ b/uidswap.c
@@ -57,7 +57,7 @@
is not part of the posix specification. */
#define SAVED_IDS_WORK_WITH_SETEUID
/* Saved effective uid. */
-static uid_t saved_euid = 0;
+static uid_t saved_euid = 0;
static gid_t saved_egid = 0;
#endif
diff --git a/umac.c b/umac.c
index 3d4e285bb..e5ec19f08 100644
--- a/umac.c
+++ b/umac.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: umac.c,v 1.20 2020/03/13 03:17:07 djm Exp $ */
+/* $OpenBSD: umac.c,v 1.21 2021/04/03 06:58:30 djm Exp $ */
/* -----------------------------------------------------------------------
*
* umac.c -- C Implementation UMAC Message Authentication
@@ -290,7 +290,7 @@ static void pdf_gen_xor(pdf_ctx *pc, const UINT8 nonce[8], UINT8 buf[8])
* versions, one expects the entire message being hashed to be passed
* in a single buffer and returns the hash result immediately. The second
* allows the message to be passed in a sequence of buffers. In the
- * muliple-buffer interface, the client calls the routine nh_update() as
+ * multiple-buffer interface, the client calls the routine nh_update() as
* many times as necessary. When there is no more data to be fed to the
* hash, the client calls nh_final() which calculates the hash output.
* Before beginning another hash calculation the nh_reset() routine
diff --git a/utf8.h b/utf8.h
index 9d6d9a32c..09941d471 100644
--- a/utf8.h
+++ b/utf8.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: utf8.h,v 1.3 2020/05/01 06:28:52 djm Exp $ */
+/* $OpenBSD: utf8.h,v 1.4 2021/04/03 06:18:41 djm Exp $ */
/*
* Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org>
*
@@ -17,12 +17,12 @@
int vasnmprintf(char **, size_t, int *, const char *, va_list);
int mprintf(const char *, ...)
- __attribute__((format(printf, 1, 2)));
+ __attribute__((format(printf, 1, 2)));
int fmprintf(FILE *, const char *, ...)
- __attribute__((format(printf, 2, 3)));
+ __attribute__((format(printf, 2, 3)));
int vfmprintf(FILE *, const char *, va_list);
int snmprintf(char *, size_t, int *, const char *, ...)
- __attribute__((format(printf, 4, 5)));
+ __attribute__((format(printf, 4, 5)));
int asmprintf(char **, size_t, int *, const char *, ...)
- __attribute__((format(printf, 4, 5)));
+ __attribute__((format(printf, 4, 5)));
void msetlocale(void);
diff --git a/version.h b/version.h
index a2eca3ec8..eba7aca06 100644
--- a/version.h
+++ b/version.h
@@ -1,6 +1,6 @@
-/* $OpenBSD: version.h,v 1.87 2020/05/06 20:58:01 djm Exp $ */
+/* $OpenBSD: version.h,v 1.92 2021/09/26 14:01:11 djm Exp $ */
-#define SSH_VERSION "OpenSSH_8.3"
+#define SSH_VERSION "OpenSSH_8.8"
#define SSH_PORTABLE "p1"
#define SSH_RELEASE SSH_VERSION SSH_PORTABLE
diff --git a/xmalloc.h b/xmalloc.h
index abaf7ada2..a6b8d23bd 100644
--- a/xmalloc.h
+++ b/xmalloc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: xmalloc.h,v 1.19 2019/11/12 22:32:48 djm Exp $ */
+/* $OpenBSD: xmalloc.h,v 1.20 2021/04/03 06:18:41 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -22,7 +22,6 @@ void *xreallocarray(void *, size_t, size_t);
void *xrecallocarray(void *, size_t, size_t, size_t);
char *xstrdup(const char *);
int xasprintf(char **, const char *, ...)
- __attribute__((__format__ (printf, 2, 3)))
- __attribute__((__nonnull__ (2)));
+ __attribute__((__format__ (printf, 2, 3))) __attribute__((__nonnull__ (2)));
int xvasprintf(char **, const char *, va_list)
- __attribute__((__nonnull__ (2)));
+ __attribute__((__nonnull__ (2)));